This is Unofficial EPICS BASE Doxygen Site
epics::pvAccess::ServerSearchHandler Class Reference

#include "responseHandlers.h"

+ Inheritance diagram for epics::pvAccess::ServerSearchHandler:
+ Collaboration diagram for epics::pvAccess::ServerSearchHandler:

Public Member Functions

 ServerSearchHandler (ServerContextImpl::shared_pointer const &context)
 
virtual ~ServerSearchHandler ()
 
virtual void handleResponse (osiSockAddr *responseFrom, Transport::shared_pointer const &transport, epics::pvData::int8 version, epics::pvData::int8 command, std::size_t payloadSize, epics::pvData::ByteBuffer *payloadBuffer) OVERRIDE FINAL
 
- Public Member Functions inherited from epics::pvAccess::AbstractServerResponseHandler
 AbstractServerResponseHandler (ServerContextImpl::shared_pointer const &context, std::string description)
 
virtual ~AbstractServerResponseHandler ()
 
- Public Member Functions inherited from epics::pvAccess::ResponseHandler
 POINTER_DEFINITIONS (ResponseHandler)
 
 ResponseHandler (Context *context, const std::string &description)
 
virtual ~ResponseHandler ()
 

Static Public Attributes

static const std::string SUPPORTED_PROTOCOL = "tcp"
 
- Static Public Attributes inherited from epics::pvAccess::ResponseHandler
static size_t num_instances
 

Additional Inherited Members

- Protected Attributes inherited from epics::pvAccess::AbstractServerResponseHandler
ServerContextImpl::shared_pointer _context
 
- Protected Attributes inherited from epics::pvAccess::ResponseHandler
std::string _description
 
epics::pvData::int32 _debugLevel
 

Detailed Description

Search channel request handler.

Definition at line 120 of file responseHandlers.h.

Constructor & Destructor Documentation

epics::pvAccess::ServerSearchHandler::ServerSearchHandler ( ServerContextImpl::shared_pointer const &  context)

Definition at line 240 of file responseHandlers.cpp.

240  :
241  AbstractServerResponseHandler(context, "Search request")
242 {
243  // initialize random seed with some random value
244  srand ( time(NULL) );
245 }
AbstractServerResponseHandler(ServerContextImpl::shared_pointer const &context, std::string description)
#define NULL
Definition: catime.c:38
virtual epics::pvAccess::ServerSearchHandler::~ServerSearchHandler ( )
inlinevirtual

Definition at line 126 of file responseHandlers.h.

126 {}

Member Function Documentation

void epics::pvAccess::ServerSearchHandler::handleResponse ( osiSockAddr responseFrom,
Transport::shared_pointer const &  transport,
epics::pvData::int8  version,
epics::pvData::int8  command,
std::size_t  payloadSize,
epics::pvData::ByteBuffer payloadBuffer 
)
virtual

Handle response.

Parameters
[in]responseFromremote address of the responder, 0 if unknown.
[in]transportresponse source transport.
[in]versionmessage version.
[in]payloadSizesize of this message data available in the payloadBuffer.
[in]payloadBuffermessage payload data. Note that this might not be the only message in the buffer. Code must not manipulate buffer.

Reimplemented from epics::pvAccess::ResponseHandler.

Definition at line 247 of file responseHandlers.cpp.

250 {
252  transport, version, command, payloadSize, payloadBuffer);
253 
254  transport->ensureData(4+1+3+16+2);
255 
256  size_t startPosition = payloadBuffer->getPosition();
257 
258  const int32 searchSequenceId = payloadBuffer->getInt();
259  const int8 qosCode = payloadBuffer->getByte();
260 
261  // reserved part
262  payloadBuffer->getByte();
263  payloadBuffer->getShort();
264 
265  osiSockAddr responseAddress;
266  memset(&responseAddress, 0, sizeof(responseAddress));
267  responseAddress.ia.sin_family = AF_INET;
268 
269  // 128-bit IPv6 address
270  if (!decodeAsIPv6Address(payloadBuffer, &responseAddress)) return;
271 
272  // accept given address if explicitly specified by sender
273  if (responseAddress.ia.sin_addr.s_addr == INADDR_ANY)
274  responseAddress.ia.sin_addr = responseFrom->ia.sin_addr;
275 
276  // NOTE: htons might be a macro (e.g. vxWorks)
277  int16 port = payloadBuffer->getShort();
278  responseAddress.ia.sin_port = htons(port);
279 
280  size_t protocolsCount = SerializeHelper::readSize(payloadBuffer, transport.get());
281  bool allowed = (protocolsCount == 0);
282  for (size_t i = 0; i < protocolsCount; i++)
283  {
284  string protocol = SerializeHelper::deserializeString(payloadBuffer, transport.get());
285  if (SUPPORTED_PROTOCOL == protocol)
286  allowed = true;
287  }
288 
289  // NOTE: we do not stop reading the buffer
290 
291  transport->ensureData(2);
292  const int32 count = payloadBuffer->getShort() & 0xFFFF;
293 
294  // TODO DoS attack?
295  // You bet! With a reply address encoded in the request we don't even need a forged UDP header.
296  const bool responseRequired = (QOS_REPLY_REQUIRED & qosCode) != 0;
297 
298  //
299  // locally broadcast if unicast (qosCode & 0x80 == 0x80) via UDP
300  //
301  if ((qosCode & 0x80) == 0x80)
302  {
303  BlockingUDPTransport::shared_pointer bt = dynamic_pointer_cast<BlockingUDPTransport>(transport);
304  if (bt && bt->hasLocalMulticastAddress())
305  {
306  // RECEIVE_BUFFER_PRE_RESERVE allows to pre-fix message
307  size_t newStartPos = (startPosition-PVA_MESSAGE_HEADER_SIZE)-PVA_MESSAGE_HEADER_SIZE-16;
308  payloadBuffer->setPosition(newStartPos);
309 
310  // copy part of a header, and add: command, payloadSize, NIF address
311  payloadBuffer->put(payloadBuffer->getBuffer(), startPosition-PVA_MESSAGE_HEADER_SIZE, PVA_MESSAGE_HEADER_SIZE-5);
312  payloadBuffer->putByte(CMD_ORIGIN_TAG);
313  payloadBuffer->putInt(16);
314  // encode this socket bind address
315  encodeAsIPv6Address(payloadBuffer, bt->getBindAddress());
316 
317  // clear unicast flag
318  payloadBuffer->put(startPosition+4, (int8)(qosCode & ~0x80));
319 
320  // update response address
321  payloadBuffer->setPosition(startPosition+8);
322  encodeAsIPv6Address(payloadBuffer, &responseAddress);
323 
324  // set to end of a message
325  payloadBuffer->setPosition(payloadBuffer->getLimit());
326 
327  bt->send(payloadBuffer->getBuffer()+newStartPos, payloadBuffer->getPosition()-newStartPos,
328  bt->getLocalMulticastAddress());
329 
330  return;
331  }
332  }
333 
334  PeerInfo::shared_pointer info;
335  if(allowed) {
336  info.reset(new PeerInfo);
337  info->transport = "pva";
338  info->peer = inetAddressToString(*responseFrom);
339  info->transportVersion = version;
340  }
341 
342  if (count > 0)
343  {
344  // regular name search
345  for (int32 i = 0; i < count; i++)
346  {
347  transport->ensureData(4);
348  const int32 cid = payloadBuffer->getInt();
349  const string name = SerializeHelper::deserializeString(payloadBuffer, transport.get());
350  // no name check here...
351 
352  if (allowed)
353  {
354  const std::vector<ChannelProvider::shared_pointer>& _providers = _context->getChannelProviders();
355 
356  int providerCount = _providers.size();
357  std::tr1::shared_ptr<ServerChannelFindRequesterImpl> tp(new ServerChannelFindRequesterImpl(_context, info, providerCount));
358  tp->set(name, searchSequenceId, cid, responseAddress, responseRequired, false);
359 
360  for (int i = 0; i < providerCount; i++)
361  _providers[i]->channelFind(name, tp);
362  }
363  }
364  }
365  else
366  {
367  // server discovery ping by pvlist
368  if (allowed)
369  {
370  // ~random hold-off to reduce impact of all servers responding.
371  // in [0.05, 0.15]
372  double delay = double(rand())/RAND_MAX; // [0, 1]
373  delay = delay*0.1 + 0.05;
374 
375  std::tr1::shared_ptr<ServerChannelFindRequesterImpl> tp(new ServerChannelFindRequesterImpl(_context, info, 1));
376  tp->set("", searchSequenceId, 0, responseAddress, true, true);
377 
378  TimerCallback::shared_pointer tc = tp;
379  _context->getTimer()->scheduleAfterDelay(tc, delay);
380  }
381  }
382 }
int8_t int8
Definition: pvType.h:75
Information provded by a client to a server-type ChannelProvider.
Definition: security.h:119
EPICS_ALWAYS_INLINE int8 getByte()
Definition: byteBuffer.h:617
static std::string deserializeString(ByteBuffer *buffer, DeserializableControl *control)
int i
Definition: scan.c:967
EPICS_ALWAYS_INLINE void putInt(int32 value)
Definition: byteBuffer.h:537
const char * getBuffer() const
Definition: byteBuffer.h:294
virtual void handleResponse(osiSockAddr *responseFrom, Transport::shared_pointer const &transport, epics::pvData::int8 version, epics::pvData::int8 command, std::size_t payloadSize, epics::pvData::ByteBuffer *payloadBuffer)
struct sockaddr_in ia
Definition: osiSock.h:157
std::size_t getLimit() const
Definition: byteBuffer.h:368
static std::size_t readSize(ByteBuffer *buffer, DeserializableControl *control)
std::size_t getPosition() const
Definition: byteBuffer.h:346
EPICS_ALWAYS_INLINE int32 getInt()
Definition: byteBuffer.h:629
void setPosition(std::size_t pos)
Definition: byteBuffer.h:357
void encodeAsIPv6Address(ByteBuffer *buffer, const osiSockAddr *address)
const epics::pvData::int16 PVA_MESSAGE_HEADER_SIZE
Definition: pvaConstants.h:47
EPICS_ALWAYS_INLINE void putByte(int8 value)
Definition: byteBuffer.h:525
EPICS_ALWAYS_INLINE int16 getShort()
Definition: byteBuffer.h:623
bool decodeAsIPv6Address(ByteBuffer *buffer, osiSockAddr *address)
static const std::string SUPPORTED_PROTOCOL
ServerContextImpl::shared_pointer _context
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:808
int16_t int16
Definition: pvType.h:79
string inetAddressToString(const osiSockAddr &addr, bool displayPort, bool displayHex)
int32_t int32
Definition: pvType.h:83

Member Data Documentation

const std::string epics::pvAccess::ServerSearchHandler::SUPPORTED_PROTOCOL = "tcp"
static

Definition at line 123 of file responseHandlers.h.


The documentation for this class was generated from the following files: