3 /// Class wrapper to encapsulate the Blackberry USB logical socket
7 Copyright (C) 2005-2009, 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_sequencePacket(true)
59 SocketZero::SocketZero( Device
&dev
,
60 int writeEndpoint
, int readEndpoint
,
61 uint8_t zeroSocketSequenceStart
)
64 m_writeEp(writeEndpoint
),
65 m_readEp(readEndpoint
),
66 m_zeroSocketSequence(zeroSocketSequenceStart
),
71 m_sequencePacket(true),
76 SocketZero::~SocketZero()
78 // nothing to close for socket zero
82 ///////////////////////////////////////
83 // Socket Zero static calls
85 // appends fragment to whole... if whole is empty, simply copies, and
86 // sets command to DATA instead of FRAGMENTED. Always updates the
87 // packet size of whole, to reflect the total size
88 void SocketZero::AppendFragment(Data
&whole
, const Data
&fragment
)
90 if( whole
.GetSize() == 0 ) {
91 // empty, so just copy
95 // has some data already, so just append
96 int size
= whole
.GetSize();
97 unsigned char *buf
= whole
.GetBuffer(size
+ fragment
.GetSize());
98 MAKE_PACKET(fpack
, fragment
);
99 int fragsize
= fragment
.GetSize() - SB_FRAG_HEADER_SIZE
;
101 memcpy(buf
+size
, &fpack
->u
.db
.u
.fragment
, fragsize
);
102 whole
.ReleaseBuffer(size
+ fragsize
);
105 // update whole's size and command type for future sanity
106 Barry::Protocol::Packet
*wpack
= (Barry::Protocol::Packet
*) whole
.GetBuffer();
107 wpack
->size
= htobs((uint16_t) whole
.GetSize());
108 wpack
->command
= SB_COMMAND_DB_DATA
;
109 // don't need to call ReleaseBuffer here, since we're not changing
110 // the real data size, and ReleaseBuffer was called above during copy
113 // If offset is 0, starts fresh, taking the first fragment packet size chunk
114 // out of whole and creating a sendable packet in fragment. Returns the
115 // next offset if there is still more data, or 0 if finished.
116 unsigned int SocketZero::MakeNextFragment(const Data
&whole
, Data
&fragment
, unsigned int offset
)
119 if( whole
.GetSize() < SB_FRAG_HEADER_SIZE
) {
120 eout("Whole packet too short to fragment: " << whole
.GetSize());
121 throw Error("Socket: Whole packet too short to fragment");
125 unsigned int todo
= whole
.GetSize() - SB_FRAG_HEADER_SIZE
- offset
;
126 unsigned int nextOffset
= 0;
127 if( todo
> (MAX_PACKET_SIZE
- SB_FRAG_HEADER_SIZE
) ) {
128 todo
= MAX_PACKET_SIZE
- SB_FRAG_HEADER_SIZE
;
129 nextOffset
= offset
+ todo
;
132 // create fragment header
133 unsigned char *buf
= fragment
.GetBuffer(SB_FRAG_HEADER_SIZE
+ todo
);
134 memcpy(buf
, whole
.GetData(), SB_FRAG_HEADER_SIZE
);
136 // copy over a fragment size of data
137 memcpy(buf
+ SB_FRAG_HEADER_SIZE
, whole
.GetData() + SB_FRAG_HEADER_SIZE
+ offset
, todo
);
139 // update fragment's size and command type
140 Barry::Protocol::Packet
*wpack
= (Barry::Protocol::Packet
*) buf
;
141 wpack
->size
= htobs((uint16_t) (todo
+ SB_FRAG_HEADER_SIZE
));
143 wpack
->command
= SB_COMMAND_DB_FRAGMENTED
;
145 wpack
->command
= SB_COMMAND_DB_DATA
;
147 // adjust the new fragment size
148 fragment
.ReleaseBuffer(SB_FRAG_HEADER_SIZE
+ todo
);
155 ///////////////////////////////////////
156 // SocketZero private API
159 // FIXME - not sure yet whether sequence ID's are per socket or not... if
160 // they are per socket, then this global sequence behaviour will not work,
161 // and we need to track m_sequenceId on a Socket level.
163 void SocketZero::CheckSequence(uint16_t socket
, const Data
&seq
)
165 MAKE_PACKET(spack
, seq
);
166 if( (unsigned int) seq
.GetSize() < SB_SEQUENCE_PACKET_SIZE
) {
167 eout("Short sequence packet:\n" << seq
);
168 throw Error("Socket: invalid sequence packet");
171 // we'll cheat here... if the packet's sequence is 0, we'll
172 // silently restart, otherwise, fail
173 uint32_t sequenceId
= btohl(spack
->u
.sequence
.sequenceId
);
174 if( sequenceId
== 0 ) {
175 // silently restart (will advance below)
179 if( sequenceId
!= m_sequenceId
) {
181 std::ostringstream oss
;
182 oss
<< "Socket 0x" << std::hex
<< (unsigned int)socket
183 << ": out of sequence. "
184 << "(Global sequence: " << m_sequenceId
185 << ". Packet sequence: " << sequenceId
188 throw Error(oss
.str());
191 dout("Bad sequence on socket 0: expected: "
193 << ". Packet sequence: " << sequenceId
);
202 void SocketZero::SendOpen(uint16_t socket
, Data
&receive
)
204 // build open command
205 Barry::Protocol::Packet packet
;
207 packet
.size
= htobs(SB_SOCKET_PACKET_HEADER_SIZE
);
208 packet
.command
= SB_COMMAND_OPEN_SOCKET
;
209 packet
.u
.socket
.socket
= htobs(socket
);
210 packet
.u
.socket
.sequence
= m_zeroSocketSequence
;// overwritten by Send()
212 Data
send(&packet
, SB_SOCKET_PACKET_HEADER_SIZE
);
216 } catch( Usb::Error
& ) {
217 eeout(send
, receive
);
222 Protocol::CheckSize(receive
, SB_PACKET_HEADER_SIZE
);
223 if( IS_COMMAND(receive
, SB_COMMAND_SEQUENCE_HANDSHAKE
) ) {
224 CheckSequence(0, receive
);
226 // still need our ACK
230 // receive now holds the Open response
233 // SHA1 hashing logic based on Rick Scott's XmBlackBerry's send_password()
234 void SocketZero::SendPasswordHash(uint16_t socket
, const char *password
, Data
&receive
)
236 unsigned char pwdigest
[SHA_DIGEST_LENGTH
];
237 unsigned char prefixedhash
[SHA_DIGEST_LENGTH
+ 4];
239 // first, hash the password by itself
240 SHA1((unsigned char *) password
, strlen(password
), pwdigest
);
242 // prefix the resulting hash with the provided seed
243 uint32_t seed
= htobl(m_challengeSeed
);
244 memcpy(&prefixedhash
[0], &seed
, sizeof(uint32_t));
245 memcpy(&prefixedhash
[4], pwdigest
, SHA_DIGEST_LENGTH
);
248 SHA1((unsigned char *) prefixedhash
, SHA_DIGEST_LENGTH
+ 4, pwdigest
);
251 size_t size
= SB_SOCKET_PACKET_HEADER_SIZE
+ PASSWORD_CHALLENGE_SIZE
;
253 // build open command
254 Barry::Protocol::Packet packet
;
256 packet
.size
= htobs(size
);
257 packet
.command
= SB_COMMAND_PASSWORD
;
258 packet
.u
.socket
.socket
= htobs(socket
);
259 packet
.u
.socket
.sequence
= m_zeroSocketSequence
;// overwritten by Send()
260 packet
.u
.socket
.u
.password
.remaining_tries
= 0;
261 packet
.u
.socket
.u
.password
.unknown
= 0;
262 packet
.u
.socket
.u
.password
.param
= htobs(0x14); // FIXME - what does this mean?
263 memcpy(packet
.u
.socket
.u
.password
.u
.hash
, pwdigest
,
264 sizeof(packet
.u
.socket
.u
.password
.u
.hash
));
266 // blank password hashes as we don't need these anymore
267 memset(pwdigest
, 0, sizeof(pwdigest
));
268 memset(prefixedhash
, 0, sizeof(prefixedhash
));
270 Data
send(&packet
, size
);
274 // blank password hash as we don't need this anymore either
275 memset(packet
.u
.socket
.u
.password
.u
.hash
, 0,
276 sizeof(packet
.u
.socket
.u
.password
.u
.hash
));
280 Protocol::CheckSize(receive
, SB_PACKET_HEADER_SIZE
);
281 if( IS_COMMAND(receive
, SB_COMMAND_SEQUENCE_HANDSHAKE
) ) {
282 CheckSequence(0, receive
);
284 // still need our ACK
288 // receive now holds the Password response
291 void SocketZero::RawSend(Data
&send
, int timeout
)
293 Usb::Device
*dev
= m_queue
? m_queue
->GetUsbDevice() : m_dev
;
295 // Special case: it seems that sending packets with a size that's an
296 // exact multiple of 0x40 causes the device to get confused.
298 // To get around that, it is observed in the captures that the size
299 // is sent in a special 3 byte packet before the real packet.
300 // Check for this case here.
302 if( (send
.GetSize() % 0x40) == 0 ) {
303 Protocol::SizePacket packet
;
304 packet
.size
= htobs(send
.GetSize());
305 packet
.buffer
[2] = 0; // zero the top byte
306 Data
sizeCommand(&packet
, 3);
308 dev
->BulkWrite(m_writeEp
, sizeCommand
);
311 dev
->BulkWrite(m_writeEp
, send
);
314 void SocketZero::RawReceive(Data
&receive
, int timeout
)
318 if( !m_queue
->DefaultRead(receive
, timeout
) )
319 throw Timeout("SocketZero::RawReceive: queue DefaultRead returned false (likely a timeout)");
322 m_dev
->BulkRead(m_readEp
, receive
, timeout
);
324 ddout("SocketZero::RawReceive: Endpoint " << m_readEp
325 << "\nReceived:\n" << receive
);
326 } while( SequencePacket(receive
) );
332 /// Returns true if this is a sequence packet that should be ignored.
333 /// This function is used in SocketZero::RawReceive() in order
334 /// to determine whether to keep reading or not. By default,
335 /// this function checks whether the packet is a sequence packet
336 /// or not, and returns true if so. Also, if it is a sequence
337 /// packet, it checks the validity of the sequence number.
339 /// If sequence packets become important in the future, this
340 /// function could be changed to call a user-defined callback,
341 /// in order to handle these things out of band.
343 bool SocketZero::SequencePacket(const Data
&data
)
345 // Begin -- Test quiet durty :(
346 if (m_sequencePacket
== false) {
349 // End -- Test quiet durty :(
351 if( data
.GetSize() >= MIN_PACKET_SIZE
) {
352 MAKE_PACKET(rpack
, data
);
353 if( rpack
->socket
== 0 &&
354 rpack
->command
== SB_COMMAND_SEQUENCE_HANDSHAKE
)
356 CheckSequence(0, data
);
360 return false; // not a sequence packet
364 ///////////////////////////////////////
365 // SocketZero public API
367 void SocketZero::SetRoutingQueue(SocketRoutingQueue
&queue
)
369 // replace the current queue pointer
373 void SocketZero::UnlinkRoutingQueue()
378 void SocketZero::Send(Data
&send
, int timeout
)
380 // force the socket number to 0
381 if( send
.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE
) {
382 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
386 // This is a socket 0 packet, so force the send packet data's
387 // socket 0 sequence number to something correct.
388 if( send
.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE
) {
389 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
390 spack
->u
.socket
.sequence
= m_zeroSocketSequence
;
391 m_zeroSocketSequence
++;
394 RawSend(send
, timeout
);
397 void SocketZero::Send(Data
&send
, Data
&receive
, int timeout
)
400 RawReceive(receive
, timeout
);
403 void SocketZero::Send(Barry::Packet
&packet
, int timeout
)
405 Send(packet
.m_send
, packet
.m_receive
, timeout
);
408 void SocketZero::Receive(Data
&receive
, int timeout
)
410 RawReceive(receive
, timeout
);
417 /// Open a logical socket on the device.
419 /// Both the socket number and the flag are based on the response to the
420 /// SELECT_MODE command. See Controller::SelectMode() for more info
423 /// The packet sequence is normal for most socket operations.
425 /// - Down: command packet with OPEN_SOCKET
426 /// - Up: optional sequence handshake packet
427 /// - Up: command response, which repeats the socket and flag data
430 /// \exception Barry::Error
431 /// Thrown on protocol error.
433 /// \exception Barry::BadPassword
434 /// Thrown on invalid password, or not enough retries left
437 SocketHandle
SocketZero::Open(uint16_t socket
, const char *password
)
439 // Things get a little funky here, as we may be left in an
440 // intermediate state in the case of a failed password.
441 // This function should support being called as many times
442 // as needed to handle the password
445 ZeroPacket
packet(send
, receive
);
447 // save sequence for later close
448 uint8_t closeFlag
= GetZeroSocketSequence();
452 m_remainingTries
= 0;
454 SendOpen(socket
, receive
);
456 // check for password challenge, or success
457 if( packet
.Command() == SB_COMMAND_PASSWORD_CHALLENGE
) {
459 m_challengeSeed
= packet
.ChallengeSeed();
460 m_remainingTries
= packet
.RemainingTries();
463 // fall through to challenge code...
467 // half open, device is expecting a password hash... do we
470 throw BadPassword("No password specified.", m_remainingTries
, false);
473 // only allow password attempts if there are
474 // BARRY_MIN_PASSWORD_TRIES or more tries remaining...
475 // we want to give the user at least some chance on a
476 // Windows machine before the device commits suicide.
477 if( m_remainingTries
< BARRY_MIN_PASSWORD_TRIES
) {
478 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.",
483 // save sequence for later close (again after SendOpen())
484 closeFlag
= GetZeroSocketSequence();
486 SendPasswordHash(socket
, password
, receive
);
488 if( packet
.Command() == SB_COMMAND_PASSWORD_FAILED
) {
490 m_challengeSeed
= packet
.ChallengeSeed();
491 m_remainingTries
= packet
.RemainingTries();
492 throw BadPassword("Password rejected by device.", m_remainingTries
, false);
495 // if we get this far, we are no longer in half-open password
496 // mode, so we can reset our flags
499 // fall through to success check...
502 if( packet
.Command() != SB_COMMAND_OPENED_SOCKET
||
503 packet
.SocketResponse() != socket
||
504 packet
.SocketSequence() != closeFlag
)
506 eout("Packet:\n" << receive
);
507 throw Error("Socket: Bad OPENED packet in Open");
510 // success! save the socket
511 return SocketHandle(new Socket(*this, socket
, closeFlag
));
517 /// Closes a non-default socket (i.e. non-zero socket number)
519 /// The packet sequence is just like Open(), except the command is
522 /// \exception Barry::Error
524 void SocketZero::Close(Socket
&socket
)
526 if( socket
.GetSocket() == 0 )
527 return; // nothing to do
529 // build close command
530 Barry::Protocol::Packet packet
;
532 packet
.size
= htobs(SB_SOCKET_PACKET_HEADER_SIZE
);
533 packet
.command
= SB_COMMAND_CLOSE_SOCKET
;
534 packet
.u
.socket
.socket
= htobs(socket
.GetSocket());
535 packet
.u
.socket
.sequence
= socket
.GetCloseFlag();
537 Data
command(&packet
, SB_SOCKET_PACKET_HEADER_SIZE
);
540 Send(command
, response
);
542 catch( Usb::Error
& ) {
543 // reset so this won't be called again
544 socket
.ForceClosed();
546 eeout(command
, response
);
550 // starting fresh, reset sequence ID
551 Protocol::CheckSize(response
, SB_PACKET_HEADER_SIZE
);
552 if( IS_COMMAND(response
, SB_COMMAND_SEQUENCE_HANDSHAKE
) ) {
553 CheckSequence(0, response
);
555 // still need our ACK
556 RawReceive(response
);
559 Protocol::CheckSize(response
, SB_SOCKET_PACKET_HEADER_SIZE
);
560 MAKE_PACKET(rpack
, response
);
561 if( rpack
->command
!= SB_COMMAND_CLOSED_SOCKET
||
562 btohs(rpack
->u
.socket
.socket
) != socket
.GetSocket() ||
563 rpack
->u
.socket
.sequence
!= socket
.GetCloseFlag() )
565 // reset so this won't be called again
566 socket
.ForceClosed();
568 eout("Packet:\n" << response
);
569 throw Error("Socket: Bad CLOSED packet in Close");
572 if( m_resetOnClose
) {
574 ZeroPacket
reset_packet(send
, receive
);
575 reset_packet
.Reset();
578 if( reset_packet
.CommandResponse() != SB_COMMAND_RESET_REPLY
) {
579 throw Error("Socket: Missing RESET_REPLY in Close");
583 // // and finally, there always seems to be an extra read of
584 // // an empty packet at the end... just throw it away
586 // RawReceive(response, 1);
588 // catch( Usb::Timeout & ) {
591 // reset socket and flag
592 socket
.ForceClosed();
600 //////////////////////////////////////////////////////////////////////////////
603 Socket::Socket( SocketZero
&zero
,
608 , m_closeFlag(closeFlag
)
609 , m_registered(false)
615 // trap exceptions in the destructor
617 // a non-default socket has been opened, close it
620 catch( std::runtime_error
&re
) {
621 // do nothing... log it?
622 dout("Exception caught in ~Socket: " << re
.what());
627 ////////////////////////////////////
628 // Socket protected API
630 void Socket::CheckSequence(const Data
&seq
)
632 m_zero
->CheckSequence(m_socket
, seq
);
635 void Socket::ForceClosed()
642 ////////////////////////////////////
647 UnregisterInterest();
648 m_zero
->Close(*this);
655 /// Sends 'send' data to device, no receive.
659 /// \exception Usb::Error on underlying bus errors.
661 void Socket::Send(Data
&send
, int timeout
)
663 // force the socket number to this socket
664 if( send
.GetSize() >= SB_PACKET_HEADER_SIZE
) {
665 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
666 spack
->socket
= htobs(m_socket
);
668 m_zero
->RawSend(send
, timeout
);
674 /// Sends 'send' data to device, and waits for response.
678 /// \exception Usb::Error on underlying bus errors.
680 void Socket::Send(Data
&send
, Data
&receive
, int timeout
)
683 Receive(receive
, timeout
);
686 void Socket::Send(Barry::Packet
&packet
, int timeout
)
688 Send(packet
.m_send
, packet
.m_receive
, timeout
);
691 void Socket::Receive(Data
&receive
, int timeout
)
694 if( m_zero
->m_queue
) {
695 if( !m_zero
->m_queue
->SocketRead(m_socket
, receive
, timeout
) )
696 throw Timeout("Socket::Receive: queue SocketRead returned false (likely a timeout)");
699 throw std::logic_error("NULL queue pointer in a registered socket read.");
703 m_zero
->RawReceive(receive
, timeout
);
708 // sends the send packet down to the device
709 // Blocks until response received or timed out in Usb::Device
710 void Socket::PacketData(Data
&send
, Data
&receive
, int timeout
)
712 if( ( send
.GetSize() < MIN_PACKET_DATA_SIZE
) ||
713 ( send
.GetSize() > MAX_PACKET_DATA_SIZE
) ) {
714 // we don't do that around here
715 throw std::logic_error("Socket: unknown send data in PacketData()");
718 Data
&inFrag
= receive
;
721 // send non-fragmented
722 Send(send
, inFrag
, timeout
);
728 // check the packet's validity
729 if( inFrag
.GetSize() > 0 ) {
730 MAKE_PACKET(rpack
, inFrag
);
734 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
736 switch( rpack
->command
)
738 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
739 CheckSequence(inFrag
);
740 if (m_zero
->GetSequencePacket() == false)
744 case SB_COMMAND_JL_READY
:
745 case SB_COMMAND_JL_ACK
:
746 case SB_COMMAND_JL_HELLO_ACK
:
747 case SB_COMMAND_JL_RESET_REQUIRED
:
751 case SB_COMMAND_JL_GET_DATA_ENTRY
: // This response means that the next packet is the stream
755 case SB_DATA_JL_INVALID
: {
756 std::ostringstream oss
;
757 oss
<< "Your Java application has been refused by your device !";
759 throw Error(oss
.str());
764 // unknown packet, pass it up to the
765 // next higher code layer
772 //std::cerr << "Blank! " << blankCount << std::endl;
773 if( blankCount
== 10 ) {
774 // only ask for more data on stalled sockets
776 throw Error("Socket: 10 blank packets received");
781 // not done yet, ask for another read
787 // sends the send packet down to the device, fragmenting if
788 // necessary, and returns the response in receive, defragmenting
790 // Blocks until response received or timed out in Usb::Device
792 // This is primarily for Desktop Database packets... Javaloader
793 // packets use PacketData().
795 void Socket::Packet(Data
&send
, Data
&receive
, int timeout
)
797 MAKE_PACKET(spack
, send
);
798 if( send
.GetSize() < MIN_PACKET_SIZE
||
799 (spack
->command
!= SB_COMMAND_DB_DATA
&&
800 spack
->command
!= SB_COMMAND_DB_DONE
) )
802 // we don't do that around here
803 eout("unknown send data in Packet(): " << send
);
804 throw std::logic_error("Socket: unknown send data in Packet()");
810 if( send
.GetSize() <= MAX_PACKET_SIZE
) {
811 // send non-fragmented
812 Send(send
, inFrag
, timeout
);
816 unsigned int offset
= 0;
820 offset
= SocketZero::MakeNextFragment(send
, outFrag
, offset
);
821 Send(outFrag
, inFrag
, timeout
);
823 MAKE_PACKET(rpack
, inFrag
);
824 // only process sequence handshakes... once we
825 // get to the last fragment, we fall through to normal
827 if( offset
&& inFrag
.GetSize() > 0 ) {
829 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
831 switch( rpack
->command
)
833 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
834 CheckSequence(inFrag
);
838 std::ostringstream oss
;
839 oss
<< "Socket: (send) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
841 throw Error(oss
.str());
848 } while( offset
> 0 );
851 bool done
= false, frag
= false;
854 MAKE_PACKET(rpack
, inFrag
);
856 // check the packet's validity
857 if( inFrag
.GetSize() > 0 ) {
860 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
862 switch( rpack
->command
)
864 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
865 CheckSequence(inFrag
);
868 case SB_COMMAND_DB_DATA
:
870 SocketZero::AppendFragment(receive
, inFrag
);
878 case SB_COMMAND_DB_FRAGMENTED
:
879 SocketZero::AppendFragment(receive
, inFrag
);
883 case SB_COMMAND_DB_DONE
:
889 std::ostringstream oss
;
890 oss
<< "Socket: (read) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
892 throw Error(oss
.str());
899 //std::cerr << "Blank! " << blankCount << std::endl;
900 if( blankCount
== 10 ) {
901 // only ask for more data on stalled sockets
903 throw Error("Socket: 10 blank packets received");
908 // not done yet, ask for another read
914 void Socket::Packet(Barry::Packet
&packet
, int timeout
)
916 Packet(packet
.m_send
, packet
.m_receive
, timeout
);
919 void Socket::Packet(Barry::JLPacket
&packet
, int timeout
)
921 if( packet
.HasData() ) {
922 SetSequencePacket(false);
923 PacketData(packet
.m_cmd
, packet
.m_receive
, timeout
);
924 SetSequencePacket(true);
925 PacketData(packet
.m_data
, packet
.m_receive
, timeout
);
928 PacketData(packet
.m_cmd
, packet
.m_receive
, timeout
);
932 void Socket::NextRecord(Data
&receive
)
934 Barry::Protocol::Packet packet
;
935 packet
.socket
= htobs(GetSocket());
936 packet
.size
= htobs(7);
937 packet
.command
= SB_COMMAND_DB_DONE
;
938 packet
.u
.db
.tableCmd
= 0;
939 packet
.u
.db
.u
.command
.operation
= 0;
941 Data
command(&packet
, 7);
942 Packet(command
, receive
);
945 void Socket::RegisterInterest(SocketRoutingQueue::SocketDataHandler handler
,
948 if( !m_zero
->m_queue
)
949 throw std::logic_error("SocketRoutingQueue required in SocketZero in order to call Socket::RegisterInterest()");
952 throw std::logic_error("Socket already registered in Socket::RegisterInterest()!");
954 m_zero
->m_queue
->RegisterInterest(m_socket
, handler
, context
);
958 void Socket::UnregisterInterest()
961 if( m_zero
->m_queue
)
962 m_zero
->m_queue
->UnregisterInterest(m_socket
);
963 m_registered
= false;