EMANE  1.2.1
controlportsession.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2016 - Adjacent Link LLC, Bridgewater, New Jersey
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * * Neither the name of Adjacent Link LLC nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "controlportsession.h"
34 #include "requestmessagehandler.h"
35 #include "remotecontrolportapi.pb.h"
36 
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <sys/uio.h>
40 
42  u32MessageSizeBytes_{},
43  u32Sequence_{}{}
44 
46 {
47  char buf[1024];
48 
49  if(u32MessageSizeBytes_ == 0)
50  {
51  ssize_t length = 0; // number of bytes received
52 
53  // read at most 4 bytes from peer to determine message length
54  length = recv(iFd,buf,4 - message_.size(),MSG_DONTWAIT);
55 
56  // if recv returns 0 or less (error), return -1 which will cause
57  // the reactor to stop detecting input events and call handle_close().
58  // This service does not specialize handle_close(), so the default
59  // implementation (base class's) is used.
60  if(length <= 0)
61  {
62  return -1;
63  }
64 
65  // save the contents of the message (frame length encoding)
66  message_.insert(message_.end(),&buf[0],&buf[length]);
67 
68  // is the entire frame length present
69  if(message_.size() == 4)
70  {
71  u32MessageSizeBytes_ = ntohl(*reinterpret_cast<std::uint32_t *>(&message_[0]));
72 
73  message_.clear();
74 
75  // a message frame of 0 length is not allowed
76  if(!u32MessageSizeBytes_)
77  {
78  return -1;
79  }
80  }
81  }
82  else
83  {
84  // attempt to read message length remaining or max buffer size
85  ssize_t length{recv(iFd,
86  buf,
87  u32MessageSizeBytes_ - message_.size() > sizeof(buf) ?
88  sizeof(buf) : u32MessageSizeBytes_ - message_.size(),
89  MSG_DONTWAIT)};
90 
91  if(length <= 0)
92  {
93  return -1;
94  }
95 
96  message_.insert(message_.end(),&buf[0],&buf[length]);
97 
98  // process message when full message is read
99  if(message_.size() == u32MessageSizeBytes_)
100  {
102 
103  if(!request.ParseFromArray(&message_[0],message_.size()))
104  {
105  // invalid message - terminate the connection
106  return -1;
107  }
108 
109  std::string sSerialization{RequestMessageHandler::process(request,
110  ++u32Sequence_)};
111 
112  std::uint32_t u32MessageFrameLength = htonl(sSerialization.size());
113 
114  iovec iov[2] =
115  {
116  {reinterpret_cast<char *>(&u32MessageFrameLength),sizeof(u32MessageFrameLength)},
117  {const_cast<char *>(sSerialization.c_str()),sSerialization.size()}
118  };
119 
120  writev(iFd,iov,2);
121 
122  message_.clear();
123 
124  u32MessageSizeBytes_ = 0;
125  }
126  }
127 
128  return 0;
129 }
static std::string process(const EMANERemoteControlPortAPI::Request &request, std::uint32_t u32Sequence)