EMANE  1.0.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 
41  u32MessageSizeBytes_{},
42  u32Sequence_{}{}
43 
45 {
46  char buf[1024];
47 
48  if(u32MessageSizeBytes_ == 0)
49  {
50  ssize_t length = 0; // number of bytes received
51 
52  // read at most 4 bytes from peer to determine message length
53  length = recv(iFd,buf,4 - message_.size(),MSG_DONTWAIT);
54 
55  // if recv returns 0 or less (error), return -1 which will cause
56  // the reactor to stop detecting input events and call handle_close().
57  // This service does not specialize handle_close(), so the default
58  // implementation (base class's) is used.
59  if(length <= 0)
60  {
61  return -1;
62  }
63 
64  // save the contents of the message (frame length encoding)
65  message_.insert(message_.end(),&buf[0],&buf[length]);
66 
67  // is the entire frame length present
68  if(message_.size() == 4)
69  {
70  u32MessageSizeBytes_ = ntohl(*reinterpret_cast<std::uint32_t *>(&message_[0]));
71 
72  message_.clear();
73 
74  // a message frame of 0 length is not allowed
75  if(!u32MessageSizeBytes_)
76  {
77  return -1;
78  }
79  }
80  }
81  else
82  {
83  // attempt to read message length remaining or max buffer size
84  ssize_t length{recv(iFd,
85  buf,
86  u32MessageSizeBytes_ - message_.size() > sizeof(buf) ?
87  sizeof(buf) : u32MessageSizeBytes_ - message_.size(),
88  MSG_DONTWAIT)};
89 
90  if(length <= 0)
91  {
92  return -1;
93  }
94 
95  message_.insert(message_.end(),&buf[0],&buf[length]);
96 
97  // process message when full message is read
98  if(message_.size() == u32MessageSizeBytes_)
99  {
100  EMANERemoteControlPortAPI::Request request{};
101 
102  if(!request.ParseFromArray(&message_[0],message_.size()))
103  {
104  // invalid message - terminate the connection
105  return -1;
106  }
107 
108  std::string sSerialization{RequestMessageHandler::process(request,
109  ++u32Sequence_)};
110 
111  std::uint32_t u32MessageFrameLength = htonl(sSerialization.size());
112 
113  iovec iov[2] =
114  {
115  {reinterpret_cast<char *>(&u32MessageFrameLength),sizeof(u32MessageFrameLength)},
116  {const_cast<char *>(sSerialization.c_str()),sSerialization.size()}
117  };
118 
119  writev(iFd,iov,2);
120 
121  message_.clear();
122 
123  u32MessageSizeBytes_ = 0;
124  }
125  }
126 
127  return 0;
128 }
static std::string process(const EMANERemoteControlPortAPI::Request &request, std::uint32_t u32Sequence)