m_raw_channel.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       m_raw_channel.cc
00003 ///             Mode class for a raw channel
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
00008     Portions Copyright (C) 2010 RealVNC Ltd.
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019     See the GNU General Public License in the COPYING file at the
00020     root directory of this project for more details.
00021 */
00022 
00023 #include "m_raw_channel.h"
00024 #include "semaphore.h"
00025 #include "data.h"
00026 #include "protocol.h"
00027 #include "protostructs.h"
00028 #include "packet.h"
00029 #include "endian.h"
00030 #include "error.h"
00031 #include "usbwrap.h"
00032 #include "controller.h"
00033 #include <stdexcept>
00034 #include <sstream>
00035 #include <cstring>
00036 #include <string>
00037 #include "protostructs.h"
00038 
00039 #include "debug.h"
00040 
00041 namespace Barry { namespace Mode {
00042 
00043 ///////////////////////////////////////////////////////////////////////////////
00044 // RawChannel SocketDataHandler callback class for data socket
00045 class RawChannelSocketHandler: public SocketRoutingQueue::SocketDataHandler
00046 {
00047         RawChannel &m_raw_channel;
00048 public:
00049         RawChannelSocketHandler(RawChannel &raw_channel)
00050                 : m_raw_channel(raw_channel)
00051         {}
00052         virtual void DataReceived(Data &data)
00053         {
00054                 m_raw_channel.HandleReceivedData(data);
00055         }
00056         virtual void Error(Barry::Error &error)
00057         {
00058                 SocketDataHandler::Error(error);
00059                 m_raw_channel.HandleError(error);
00060         }
00061         virtual ~RawChannelSocketHandler()
00062         {}
00063 };
00064 
00065 ///////////////////////////////////////////////////////////////////////////////
00066 // RawChannel SocketDataHandler callback class for zero socket
00067 class RawChannelZeroSocketHandler: public SocketRoutingQueue::SocketDataHandler
00068 {
00069         RawChannel &m_raw_channel;
00070 public:
00071         RawChannelZeroSocketHandler(RawChannel &raw_channel)
00072                 : m_raw_channel(raw_channel)
00073         {}
00074         virtual void DataReceived(Data &data)
00075         {
00076                 m_raw_channel.HandleReceivedZeroPacket(data);
00077         }
00078         virtual void Error(Barry::Error &error)
00079         {
00080                 SocketDataHandler::Error(error);
00081                 m_raw_channel.HandleError(error);
00082         }
00083         virtual ~RawChannelZeroSocketHandler()
00084         {}
00085 };
00086 
00087 ///////////////////////////////////////////////////////////////////////////////
00088 // RawChannel Mode class
00089 
00090 RawChannel::RawChannel(Controller &con, RawChannelDataCallback &callback)
00091         : Mode(con, Controller::RawChannel)
00092         , m_callback(&callback)
00093         , m_send_buffer(NULL)
00094         , m_zero_registered(false)
00095         , m_pending_error(NULL)
00096 {
00097         CheckQueueAvailable();
00098         InitBuffer();
00099 }
00100 
00101 RawChannel::RawChannel(Controller &con)
00102         : Mode(con, Controller::RawChannel)
00103         , m_callback(NULL)
00104         , m_send_buffer(NULL)
00105         , m_zero_registered(false)
00106         , m_pending_error(NULL)
00107 {
00108         CheckQueueAvailable();
00109         InitBuffer();
00110 }
00111 
00112 void RawChannel::CheckQueueAvailable()
00113 {
00114         if( !m_con.HasQueue() ) {
00115                 throw Barry::Error("RawChannel: No routing queue set in controller");
00116         }
00117 }
00118 
00119 void RawChannel::InitBuffer()
00120 {
00121         m_send_buffer = new unsigned char[SB_CHANNELPACKET_HEADER_SIZE + SB_CHANNELPACKET_MAX_DATA_SIZE];
00122 }
00123 
00124 RawChannel::~RawChannel()
00125 {
00126         UnregisterZeroSocketInterest();
00127 
00128         delete[] m_send_buffer;
00129 
00130         delete m_pending_error;
00131 }
00132 
00133 void RawChannel::OnOpen()
00134 {
00135         // Enable sequence packets so that DataSendAck callback and close can be
00136         // implemented
00137         m_zero_registered = true;
00138         SocketRoutingQueue::SocketDataHandlerPtr zeroCallback;
00139         zeroCallback.reset(new RawChannelZeroSocketHandler(*this));
00140         m_con.GetQueue()->RegisterInterest(0, zeroCallback);
00141         // Get socket data packets routed to this class as well if a
00142         // callback was provided, otherside just get the data packets
00143         // placed into a queue for the socket.
00144         if( m_callback ) {
00145                 SocketRoutingQueue::SocketDataHandlerPtr callback;
00146                 callback.reset(new RawChannelSocketHandler(*this));
00147                 m_socket->UnregisterInterest();
00148                 m_socket->RegisterInterest(callback);
00149         }
00150         else {
00151                 // sockets already register themselves by default,
00152                 // so no need to do anything in this case
00153         }
00154 }
00155 
00156 
00157 void RawChannel::HandleReceivedZeroPacket(Data &data)
00158 {
00159         Protocol::CheckSize(data, SB_PACKET_HEADER_SIZE);
00160         MAKE_PACKETPTR_BUF(packet, data.GetData());
00161 
00162         if( packet->socket != 0 ) {
00163                 UnregisterZeroSocketInterest();
00164                 SetPendingError("RawChannel: Got packet not for socket-zero");
00165         }
00166 
00167         switch( btohs(packet->command) )
00168         {
00169         case SB_COMMAND_CLOSE_SOCKET:
00170         case SB_COMMAND_REMOTE_CLOSE_SOCKET:
00171                 // Stop listening to socket 0 messages
00172                 // so that socket close work.
00173                 UnregisterZeroSocketInterest();
00174                 if( m_callback ) {
00175                         m_callback->ChannelClose();
00176                 }
00177 
00178                 break;
00179         default:
00180                 UnregisterZeroSocketInterest();
00181                 if( m_callback ) {
00182                         m_callback->ChannelError("RawChannel: Got unexpected socket zero packet");
00183                 }
00184                 else {
00185                         SetPendingError("RawChannel: Got unexpected socket zero packet");
00186                 }
00187                 break;
00188         }
00189 
00190 }
00191 
00192 void RawChannel::HandleReceivedData(Data &data)
00193 {
00194         // Only ever called in callback mode
00195         ValidateDataPacket(data);
00196         MAKE_CHANNELPACKETPTR_BUF(packet, data.GetData());
00197 
00198         // Should be a socket packet for us, so remove packet headers
00199         Data partial(packet->u.data, data.GetSize() - SB_CHANNELPACKET_HEADER_SIZE);
00200         if( m_callback ) {
00201                 m_callback->DataReceived(partial);
00202         }
00203         else {
00204                 SetPendingError("RawChannel: Received data to handle when in non-callback mode");
00205         }
00206 }
00207 
00208 void RawChannel::HandleError(Barry::Error &error)
00209 {
00210         std::ostringstream errorOss;
00211         errorOss << "RawChannel: Socket error received, what: " << error.what();
00212 
00213         if( m_callback ) {
00214                 m_callback->ChannelError(errorOss.str().c_str());
00215         }
00216         else {
00217                 SetPendingError(errorOss.str().c_str());
00218         }
00219 }
00220 
00221 void RawChannel::UnregisterZeroSocketInterest()
00222 {
00223         if( m_zero_registered ) {
00224                 m_con.GetQueue()->UnregisterInterest(0);
00225                 m_zero_registered = false;
00226         }
00227 }
00228 
00229 void RawChannel::SetPendingError(const char *msg)
00230 {
00231         if( !m_pending_error ) {
00232                 m_pending_error = new std::string(msg);
00233         }
00234 }
00235 
00236 ///////////////////////////////////////////////////////////////////////////////
00237 // public API
00238 
00239 void RawChannel::Send(Data &data, int timeout)
00240 {
00241         size_t packetSize = SB_CHANNELPACKET_HEADER_SIZE + data.GetSize();
00242 
00243         if( packetSize > SB_CHANNELPACKET_HEADER_SIZE + SB_CHANNELPACKET_MAX_DATA_SIZE ) {
00244                 throw Barry::Error("RawChannel: send data size larger than MaximumPacketSize");
00245         }
00246 
00247         if( m_pending_error ) {
00248                 throw Barry::Error(*m_pending_error);
00249         }
00250 
00251         // setup header and copy data in
00252         MAKE_CHANNELPACKETPTR_BUF(packet, m_send_buffer);
00253         packet->size = htobs(packetSize);
00254         std::memcpy(packet->u.data, data.GetData(), data.GetSize());
00255 
00256         Data toSend(m_send_buffer, packetSize);
00257         m_socket->SyncSend(toSend, timeout);
00258 
00259         if( m_pending_error ) {
00260                 throw Barry::Error(*m_pending_error);
00261         }
00262 }
00263 
00264 void RawChannel::Receive(Data &data,int timeout)
00265 {
00266         if( m_callback ) {
00267                 throw std::logic_error("RawChannel: Receive called when channel was created with a callback");
00268         }
00269 
00270         if( m_pending_error ) {
00271                 throw Barry::Error(*m_pending_error);
00272         }
00273 
00274         // Receive into a buffer
00275         m_socket->Receive(m_receive_data, timeout);
00276         // Then transfer across, skipping the header
00277         ValidateDataPacket(m_receive_data);
00278         MAKE_CHANNELPACKETPTR_BUF(packet, m_receive_data.GetData());
00279 
00280         size_t len = packet->size - SB_CHANNELPACKET_HEADER_SIZE;
00281         memcpy(data.GetBuffer(), packet->u.data, len);
00282         data.ReleaseBuffer(len);
00283 
00284 }
00285 
00286 void RawChannel::ValidateDataPacket(Data &data)
00287 {
00288         Protocol::CheckSize(data, SB_CHANNELPACKET_HEADER_SIZE);
00289         MAKE_CHANNELPACKETPTR_BUF(packet, data.GetData());
00290         if( packet->size != data.GetSize() ) {
00291 
00292                 throw std::logic_error("RawChannel: Data size doesn't match packet size");
00293         }
00294 }
00295 
00296 size_t RawChannel::MaximumSendSize()
00297 {
00298         return SB_CHANNELPACKET_MAX_DATA_SIZE;
00299 }
00300 
00301 }} // namespace Barry::Mode