3 /// Class wrapper to encapsulate the Blackberry USB logical socket
7 Copyright (C) 2005-2010, 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_hideSequencePacket(true),
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_hideSequencePacket(true),
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 } catch( Usb::Error
& ) {
218 eeout(send
, receive
);
223 Protocol::CheckSize(receive
, SB_PACKET_HEADER_SIZE
);
224 if( IS_COMMAND(receive
, SB_COMMAND_SEQUENCE_HANDSHAKE
) ) {
225 CheckSequence(0, receive
);
227 // still need our ACK
231 // receive now holds the Open response
234 // SHA1 hashing logic based on Rick Scott's XmBlackBerry's send_password()
235 void SocketZero::SendPasswordHash(uint16_t socket
, const char *password
, Data
&receive
)
237 unsigned char pwdigest
[SHA_DIGEST_LENGTH
];
238 unsigned char prefixedhash
[SHA_DIGEST_LENGTH
+ 4];
240 // first, hash the password by itself
241 SHA1((unsigned char *) password
, strlen(password
), pwdigest
);
243 // prefix the resulting hash with the provided seed
244 uint32_t seed
= htobl(m_challengeSeed
);
245 memcpy(&prefixedhash
[0], &seed
, sizeof(uint32_t));
246 memcpy(&prefixedhash
[4], pwdigest
, SHA_DIGEST_LENGTH
);
249 SHA1((unsigned char *) prefixedhash
, SHA_DIGEST_LENGTH
+ 4, pwdigest
);
252 size_t size
= SB_SOCKET_PACKET_HEADER_SIZE
+ PASSWORD_CHALLENGE_SIZE
;
254 // build open command
255 Barry::Protocol::Packet packet
;
257 packet
.size
= htobs(size
);
258 packet
.command
= SB_COMMAND_PASSWORD
;
259 packet
.u
.socket
.socket
= htobs(socket
);
260 packet
.u
.socket
.sequence
= m_zeroSocketSequence
;// overwritten by Send()
261 packet
.u
.socket
.u
.password
.remaining_tries
= 0;
262 packet
.u
.socket
.u
.password
.unknown
= 0;
263 packet
.u
.socket
.u
.password
.param
= htobs(0x14); // FIXME - what does this mean?
264 memcpy(packet
.u
.socket
.u
.password
.u
.hash
, pwdigest
,
265 sizeof(packet
.u
.socket
.u
.password
.u
.hash
));
267 // blank password hashes as we don't need these anymore
268 memset(pwdigest
, 0, sizeof(pwdigest
));
269 memset(prefixedhash
, 0, sizeof(prefixedhash
));
271 Data
send(&packet
, size
);
275 // blank password hash as we don't need this anymore either
276 memset(packet
.u
.socket
.u
.password
.u
.hash
, 0,
277 sizeof(packet
.u
.socket
.u
.password
.u
.hash
));
281 Protocol::CheckSize(receive
, SB_PACKET_HEADER_SIZE
);
282 if( IS_COMMAND(receive
, SB_COMMAND_SEQUENCE_HANDSHAKE
) ) {
283 CheckSequence(0, receive
);
285 // still need our ACK
289 // receive now holds the Password response
292 void SocketZero::RawSend(Data
&send
, int timeout
)
294 Usb::Device
*dev
= m_queue
? m_queue
->GetUsbDevice() : m_dev
;
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
)
319 if( !m_queue
->DefaultRead(receive
, timeout
) )
320 throw Timeout("SocketZero::RawReceive: queue DefaultRead returned false (likely a timeout)");
323 m_dev
->BulkRead(m_readEp
, receive
, timeout
);
325 ddout("SocketZero::RawReceive: Endpoint "
326 << (m_queue
? m_queue
->GetReadEp() : m_readEp
)
327 << "\nReceived:\n" << receive
);
328 } while( SequencePacket(receive
) );
334 /// Returns true if this is a sequence packet that should be ignored.
335 /// This function is used in SocketZero::RawReceive() in order
336 /// to determine whether to keep reading or not. By default,
337 /// this function checks whether the packet is a sequence packet
338 /// or not, and returns true if so. Also, if it is a sequence
339 /// packet, it checks the validity of the sequence number.
341 /// If sequence packets become important in the future, this
342 /// function could be changed to call a user-defined callback,
343 /// in order to handle these things out of band.
345 bool SocketZero::SequencePacket(const Data
&data
)
347 // Begin -- Test quiet durty :(
348 if (m_hideSequencePacket
== false) {
351 // End -- Test quiet durty :(
353 if( data
.GetSize() >= MIN_PACKET_SIZE
) {
354 MAKE_PACKET(rpack
, data
);
355 if( rpack
->socket
== 0 &&
356 rpack
->command
== SB_COMMAND_SEQUENCE_HANDSHAKE
)
358 CheckSequence(0, data
);
362 return false; // not a sequence packet
366 ///////////////////////////////////////
367 // SocketZero public API
369 void SocketZero::SetRoutingQueue(SocketRoutingQueue
&queue
)
371 // replace the current queue pointer
375 void SocketZero::UnlinkRoutingQueue()
380 void SocketZero::Send(Data
&send
, int timeout
)
382 // force the socket number to 0
383 if( send
.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE
) {
384 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
388 // This is a socket 0 packet, so force the send packet data's
389 // socket 0 sequence number to something correct.
390 if( send
.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE
) {
391 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
392 spack
->u
.socket
.sequence
= m_zeroSocketSequence
;
393 m_zeroSocketSequence
++;
396 RawSend(send
, timeout
);
399 void SocketZero::Send(Data
&send
, Data
&receive
, int timeout
)
402 RawReceive(receive
, timeout
);
405 void SocketZero::Send(Barry::Packet
&packet
, int timeout
)
407 Send(packet
.m_send
, packet
.m_receive
, timeout
);
410 void SocketZero::Receive(Data
&receive
, int timeout
)
412 RawReceive(receive
, timeout
);
419 /// Open a logical socket on the device.
421 /// Both the socket number and the flag are based on the response to the
422 /// SELECT_MODE command. See Controller::SelectMode() for more info
425 /// The packet sequence is normal for most socket operations.
427 /// - Down: command packet with OPEN_SOCKET
428 /// - Up: optional sequence handshake packet
429 /// - Up: command response, which repeats the socket and flag data
432 /// \exception Barry::Error
433 /// Thrown on protocol error.
435 /// \exception Barry::BadPassword
436 /// Thrown on invalid password, or not enough retries left
439 SocketHandle
SocketZero::Open(uint16_t socket
, const char *password
)
441 // Things get a little funky here, as we may be left in an
442 // intermediate state in the case of a failed password.
443 // This function should support being called as many times
444 // as needed to handle the password
447 ZeroPacket
packet(send
, receive
);
449 // save sequence for later close
450 uint8_t closeFlag
= GetZeroSocketSequence();
454 m_remainingTries
= 0;
456 SendOpen(socket
, receive
);
458 // check for password challenge, or success
459 if( packet
.Command() == SB_COMMAND_PASSWORD_CHALLENGE
) {
461 m_challengeSeed
= packet
.ChallengeSeed();
462 m_remainingTries
= packet
.RemainingTries();
465 // fall through to challenge code...
469 // half open, device is expecting a password hash... do we
472 throw BadPassword("No password specified.", m_remainingTries
, false);
475 // only allow password attempts if there are
476 // BARRY_MIN_PASSWORD_TRIES or more tries remaining...
477 // we want to give the user at least some chance on a
478 // Windows machine before the device commits suicide.
479 if( m_remainingTries
< BARRY_MIN_PASSWORD_TRIES
) {
480 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.",
485 // save sequence for later close (again after SendOpen())
486 closeFlag
= GetZeroSocketSequence();
488 SendPasswordHash(socket
, password
, receive
);
490 if( packet
.Command() == SB_COMMAND_PASSWORD_FAILED
) {
492 m_challengeSeed
= packet
.ChallengeSeed();
493 m_remainingTries
= packet
.RemainingTries();
494 throw BadPassword("Password rejected by device.", m_remainingTries
, false);
497 // if we get this far, we are no longer in half-open password
498 // mode, so we can reset our flags
501 // fall through to success check...
504 // If the device thinks that the socket was already open then
505 // it will tell us by sending an SB_COMMAND_CLOSE_SOCKET.
507 // This happens most commonly when using raw channels which
508 // haven't been cleanly closed (such as by killing the process
509 // running Barry) and so the device still thinks the socket
512 // Retrying the open will usually succeed, but relies on the
513 // device software re-creating the channel after it's closed
514 // so return an error here instead of automatically retrying.
515 if( packet
.Command() == SB_COMMAND_CLOSE_SOCKET
)
517 throw Error("Socket: Device closed socket when trying to open");
520 if( packet
.Command() != SB_COMMAND_OPENED_SOCKET
||
521 packet
.SocketResponse() != socket
||
522 packet
.SocketSequence() != closeFlag
)
524 eout("Packet:\n" << receive
);
525 throw Error("Socket: Bad OPENED packet in Open");
528 // success! save the socket
529 return SocketHandle(new Socket(*this, socket
, closeFlag
));
535 /// Closes a non-default socket (i.e. non-zero socket number)
537 /// The packet sequence is just like Open(), except the command is
540 /// \exception Barry::Error
542 void SocketZero::Close(Socket
&socket
)
544 if( socket
.GetSocket() == 0 )
545 return; // nothing to do
547 // build close command
548 Barry::Protocol::Packet packet
;
550 packet
.size
= htobs(SB_SOCKET_PACKET_HEADER_SIZE
);
551 packet
.command
= SB_COMMAND_CLOSE_SOCKET
;
552 packet
.u
.socket
.socket
= htobs(socket
.GetSocket());
553 packet
.u
.socket
.sequence
= socket
.GetCloseFlag();
555 Data
command(&packet
, SB_SOCKET_PACKET_HEADER_SIZE
);
558 Send(command
, response
);
560 catch( Usb::Error
& ) {
561 // reset so this won't be called again
562 socket
.ForceClosed();
564 eeout(command
, response
);
568 // starting fresh, reset sequence ID
569 Protocol::CheckSize(response
, SB_PACKET_HEADER_SIZE
);
570 if( IS_COMMAND(response
, SB_COMMAND_SEQUENCE_HANDSHAKE
) ) {
571 CheckSequence(0, response
);
573 // still need our ACK
574 RawReceive(response
);
577 Protocol::CheckSize(response
, SB_SOCKET_PACKET_HEADER_SIZE
);
578 MAKE_PACKET(rpack
, response
);
579 // The reply will be SB_COMMAND_CLOSED_SOCKET if the device
580 // has closed the socket in response to our request.
582 // It's also possible for the reply to be
583 // SB_COMMAND_REMOTE_CLOSE_SOCKET if the device wanted to
584 // close the socket at the same time, such as if the channel
585 // API is being used by the device.
586 if( ( rpack
->command
!= SB_COMMAND_CLOSED_SOCKET
&&
587 rpack
->command
!= SB_COMMAND_REMOTE_CLOSE_SOCKET
) ||
588 btohs(rpack
->u
.socket
.socket
) != socket
.GetSocket() ||
589 rpack
->u
.socket
.sequence
!= socket
.GetCloseFlag() )
591 // reset so this won't be called again
592 socket
.ForceClosed();
594 eout("Packet:\n" << response
);
595 throw BadPacket(rpack
->command
, "Socket: Bad CLOSED packet in Close");
598 if( m_resetOnClose
) {
600 ZeroPacket
reset_packet(send
, receive
);
601 reset_packet
.Reset();
604 if( reset_packet
.CommandResponse() != SB_COMMAND_RESET_REPLY
) {
605 throw BadPacket(reset_packet
.CommandResponse(),
606 "Socket: Missing RESET_REPLY in Close");
610 // // and finally, there always seems to be an extra read of
611 // // an empty packet at the end... just throw it away
613 // RawReceive(response, 1);
615 // catch( Usb::Timeout & ) {
618 // reset socket and flag
619 socket
.ForceClosed();
625 /// Clears the USB Halt bit on both the read and write endpoints
627 void SocketZero::ClearHalt()
629 // clear the read endpoint
631 m_dev
->ClearHalt(m_queue
->GetReadEp());
634 m_dev
->ClearHalt(m_readEp
);
637 // clear the write endpoint
638 m_dev
->ClearHalt(m_writeEp
);
646 //////////////////////////////////////////////////////////////////////////////
649 Socket::Socket( SocketZero
&zero
,
654 , m_closeFlag(closeFlag
)
655 , m_registered(false)
661 // trap exceptions in the destructor
663 // a non-default socket has been opened, close it
666 catch( std::runtime_error
&re
) {
667 // do nothing... log it?
668 dout("Exception caught in ~Socket: " << re
.what());
673 ////////////////////////////////////
674 // Socket protected API
676 void Socket::CheckSequence(const Data
&seq
)
678 m_zero
->CheckSequence(m_socket
, seq
);
681 void Socket::ForceClosed()
688 ////////////////////////////////////
693 UnregisterInterest();
694 m_zero
->Close(*this);
701 /// Sends 'send' data to device, no receive.
705 /// \exception Usb::Error on underlying bus errors.
707 void Socket::Send(Data
&send
, int timeout
)
709 // force the socket number to this socket
710 if( send
.GetSize() >= SB_PACKET_HEADER_SIZE
) {
711 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
712 spack
->socket
= htobs(m_socket
);
714 m_zero
->RawSend(send
, timeout
);
720 /// Sends 'send' data to device, and waits for response.
724 /// \exception Usb::Error on underlying bus errors.
726 void Socket::Send(Data
&send
, Data
&receive
, int timeout
)
729 Receive(receive
, timeout
);
732 void Socket::Send(Barry::Packet
&packet
, int timeout
)
734 Send(packet
.m_send
, packet
.m_receive
, timeout
);
737 void Socket::Receive(Data
&receive
, int timeout
)
740 if( m_zero
->m_queue
) {
741 if( !m_zero
->m_queue
->SocketRead(m_socket
, receive
, timeout
) )
742 throw Timeout("Socket::Receive: queue SocketRead returned false (likely a timeout)");
745 throw std::logic_error("NULL queue pointer in a registered socket read.");
749 m_zero
->RawReceive(receive
, timeout
);
754 // FIXME - find a better way to do this?
755 void Socket::ReceiveData(Data
&receive
, int timeout
)
757 HideSequencePacket(false);
759 HideSequencePacket(true);
762 void Socket::ClearHalt()
768 // FIXME - find a better way to do this?
769 void Socket::InitSequence(int timeout
)
774 HideSequencePacket(false);
776 HideSequencePacket(true);
778 Protocol::CheckSize(receive
, SB_PACKET_HEADER_SIZE
);
779 CheckSequence(receive
);
783 // sends the send packet down to the device
784 // Blocks until response received or timed out in Usb::Device
786 // This function is used to send packet to JVM
787 void Socket::PacketJVM(Data
&send
, Data
&receive
, int timeout
)
789 if( ( send
.GetSize() < MIN_PACKET_DATA_SIZE
) ||
790 ( send
.GetSize() > MAX_PACKET_DATA_SIZE
) ) {
791 // we don't do that around here
792 throw std::logic_error("Socket: unknown send data in PacketJVM()");
795 Data
&inFrag
= receive
;
798 // send non-fragmented
799 Send(send
, inFrag
, timeout
);
805 // check the packet's validity
806 if( inFrag
.GetSize() > 6 ) {
807 MAKE_PACKET(rpack
, inFrag
);
811 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
813 switch( rpack
->command
)
815 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
816 CheckSequence(inFrag
);
820 std::ostringstream oss
;
821 oss
<< "Socket: (read) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
823 throw Error(oss
.str());
828 else if( inFrag
.GetSize() == 6 ) {
834 //std::cerr << "Blank! " << blankCount << std::endl;
835 if( blankCount
== 10 ) {
836 // only ask for more data on stalled sockets
838 throw Error("Socket: 10 blank packets received");
843 // not done yet, ask for another read
849 // sends the send packet down to the device
850 // Blocks until response received or timed out in Usb::Device
851 void Socket::PacketData(Data
&send
, Data
&receive
, int timeout
)
853 if( ( send
.GetSize() < MIN_PACKET_DATA_SIZE
) ||
854 ( send
.GetSize() > MAX_PACKET_DATA_SIZE
) ) {
855 // we don't do that around here
856 throw std::logic_error("Socket: unknown send data in PacketData()");
859 Data
&inFrag
= receive
;
862 // send non-fragmented
863 Send(send
, inFrag
, timeout
);
869 // check the packet's validity
870 if( inFrag
.GetSize() > 0 ) {
871 MAKE_PACKET(rpack
, inFrag
);
875 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
877 switch( rpack
->command
)
879 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
880 CheckSequence(inFrag
);
881 if (!m_zero
->IsSequencePacketHidden())
885 case SB_COMMAND_JL_READY
:
886 case SB_COMMAND_JL_ACK
:
887 case SB_COMMAND_JL_HELLO_ACK
:
888 case SB_COMMAND_JL_RESET_REQUIRED
:
892 case SB_COMMAND_JL_GET_DATA_ENTRY
: // This response means that the next packet is the stream
896 case SB_DATA_JL_INVALID
:
897 throw BadPacket(rpack
->command
, "file is not a valid Java code file");
900 case SB_COMMAND_JL_NOT_SUPPORTED
:
901 throw BadPacket(rpack
->command
, "device does not support requested command");
905 // unknown packet, pass it up to the
906 // next higher code layer
913 //std::cerr << "Blank! " << blankCount << std::endl;
914 if( blankCount
== 10 ) {
915 // only ask for more data on stalled sockets
917 throw Error("Socket: 10 blank packets received");
922 // not done yet, ask for another read
928 // sends the send packet down to the device, fragmenting if
929 // necessary, and returns the response in receive, defragmenting
931 // Blocks until response received or timed out in Usb::Device
933 // This is primarily for Desktop Database packets... Javaloader
934 // packets use PacketData().
936 void Socket::Packet(Data
&send
, Data
&receive
, int timeout
)
938 MAKE_PACKET(spack
, send
);
939 if( send
.GetSize() < MIN_PACKET_SIZE
||
940 (spack
->command
!= SB_COMMAND_DB_DATA
&&
941 spack
->command
!= SB_COMMAND_DB_DONE
) )
943 // we don't do that around here
944 eout("unknown send data in Packet(): " << send
);
945 throw std::logic_error("Socket: unknown send data in Packet()");
951 if( send
.GetSize() <= MAX_PACKET_SIZE
) {
952 // send non-fragmented
953 Send(send
, inFrag
, timeout
);
957 unsigned int offset
= 0;
960 // You haven't to sequence packet while the whole packet isn't sent
961 // a) No sequence received packet
962 // b) 1°) Sent framgment 1/N
963 // 2°) Sent framgment 2/N
965 // N°) Before sent fragment N/N, I enable the sequence packet process.
966 // Sent framgment N/N
967 HideSequencePacket(false);
970 offset
= SocketZero::MakeNextFragment(send
, outFrag
, offset
);
973 MAKE_PACKET(spack
, outFrag
);
975 if (spack
->command
!= SB_COMMAND_DB_FRAGMENTED
)
976 HideSequencePacket(true);
978 Send(outFrag
, inFrag
, timeout
);
980 // only process sequence handshakes... once we
981 // get to the last fragment, we fall through to normal
983 if (spack
->command
!= SB_COMMAND_DB_FRAGMENTED
) {
984 MAKE_PACKET(rpack
, inFrag
);
986 if( offset
&& inFrag
.GetSize() > 0 ) {
987 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
989 switch( rpack
->command
)
991 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
992 CheckSequence(inFrag
);
996 std::ostringstream oss
;
997 oss
<< "Socket: (send) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
999 throw Error(oss
.str());
1006 } while( offset
> 0 );
1008 // To be sure that it's clean...
1009 HideSequencePacket(true);
1012 bool done
= false, frag
= false;
1015 MAKE_PACKET(rpack
, inFrag
);
1017 // check the packet's validity
1018 if( inFrag
.GetSize() > 0 ) {
1021 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
1023 switch( rpack
->command
)
1025 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
1026 CheckSequence(inFrag
);
1029 case SB_COMMAND_DB_DATA
:
1031 SocketZero::AppendFragment(receive
, inFrag
);
1039 case SB_COMMAND_DB_FRAGMENTED
:
1040 SocketZero::AppendFragment(receive
, inFrag
);
1044 case SB_COMMAND_DB_DONE
:
1050 std::ostringstream oss
;
1051 oss
<< "Socket: (read) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
1053 throw Error(oss
.str());
1060 //std::cerr << "Blank! " << blankCount << std::endl;
1061 if( blankCount
== 10 ) {
1062 // only ask for more data on stalled sockets
1064 throw Error("Socket: 10 blank packets received");
1069 // not done yet, ask for another read
1075 void Socket::Packet(Barry::Packet
&packet
, int timeout
)
1077 Packet(packet
.m_send
, packet
.m_receive
, timeout
);
1080 void Socket::Packet(Barry::JLPacket
&packet
, int timeout
)
1082 if( packet
.HasData() ) {
1083 HideSequencePacket(false);
1084 PacketData(packet
.m_cmd
, packet
.m_receive
, timeout
);
1085 HideSequencePacket(true);
1086 PacketData(packet
.m_data
, packet
.m_receive
, timeout
);
1089 PacketData(packet
.m_cmd
, packet
.m_receive
, timeout
);
1093 void Socket::Packet(Barry::JVMPacket
&packet
, int timeout
)
1095 HideSequencePacket(false);
1096 PacketJVM(packet
.m_cmd
, packet
.m_receive
, timeout
);
1097 HideSequencePacket(true);
1100 void Socket::NextRecord(Data
&receive
)
1102 Barry::Protocol::Packet packet
;
1103 packet
.socket
= htobs(GetSocket());
1104 packet
.size
= htobs(7);
1105 packet
.command
= SB_COMMAND_DB_DONE
;
1106 packet
.u
.db
.tableCmd
= 0;
1107 packet
.u
.db
.u
.command
.operation
= 0;
1109 Data
command(&packet
, 7);
1110 Packet(command
, receive
);
1113 void Socket::RegisterInterest(SocketRoutingQueue::SocketDataHandlerPtr handler
)
1115 if( !m_zero
->m_queue
)
1116 throw std::logic_error("SocketRoutingQueue required in SocketZero in order to call Socket::RegisterInterest()");
1119 throw std::logic_error("Socket already registered in Socket::RegisterInterest()!");
1121 m_zero
->m_queue
->RegisterInterest(m_socket
, handler
);
1122 m_registered
= true;
1125 void Socket::UnregisterInterest()
1127 if( m_registered
) {
1128 if( m_zero
->m_queue
)
1129 m_zero
->m_queue
->UnregisterInterest(m_socket
);
1130 m_registered
= false;
1135 } // namespace Barry