Simple Geolocalization and Course Transmission Protocol (SGCTP)
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Friends Macros Pages
transmit.cpp
Go to the documentation of this file.
1 // INDENTING (emacs/vi): -*- mode:c++; tab-width:2; c-basic-offset:2; intent-tabs-mode:nil; -*- ex: set tabstop=2 expandtab:
2 
3 /*
4  * Simple Geolocalization and Course Transmission Protocol (SGCTP)
5  * Copyright (C) 2014 Cedric Dufour <http://cedric.dufour.name>
6  *
7  * The Simple Geolocalization and Course Transmission Protocol (SGCTP) is
8  * free software:
9  * you can redistribute it and/or modify it under the terms of the GNU General
10  * Public License as published by the Free Software Foundation, Version 3.
11  *
12  * The Simple Geolocalization and Course Transmission Protocol (SGCTP) is
13  * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15  * PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  */
19 
20 // C
21 #include <errno.h>
22 #include <string.h>
23 #include <arpa/inet.h>
24 #include <sys/socket.h>
25 
26 // SGCTP
27 #include "sgctp/data.hpp"
28 #include "sgctp/payload.hpp"
29 #include "sgctp/payload_aes128.hpp"
30 #include "sgctp/principal.hpp"
31 #include "sgctp/transmit.hpp"
32 #include "sgctp/transmit_file.hpp"
33 #include "sgctp/transmit_udp.hpp"
34 #include "sgctp/transmit_tcp.hpp"
35 using namespace SGCTP;
36 
37 
38 //----------------------------------------------------------------------
39 // CONSTRUCTORS / DESTRUCTOR
40 //----------------------------------------------------------------------
41 
43  : CParameters()
44  , pucBuffer( NULL )
45  , iBufferSize( 0 )
46  , iBufferDataStart( 0 )
47  , iBufferDataEnd( 0 )
48  , fdTimeout( 0.0 )
49  , poPayload( NULL )
50  , ePayloadType( PAYLOAD_UNDEFINED )
51 {}
52 
54 {
55  if( pucBuffer )
57  if( poPayload )
58  delete poPayload;
59 }
60 
61 
62 //----------------------------------------------------------------------
63 // METHODS
64 //----------------------------------------------------------------------
65 
67 {
68  if( !pucBuffer )
69  {
71  if( !pucBuffer )
72  return -ENOMEM;
74  iBufferDataStart = 0;
75  iBufferDataEnd = 0;
76  }
77  return 0;
78 }
79 
80 int CTransmit::recvBuffer( int _iDescriptor,
81  int _iSize )
82 {
83  int __iReturn;
84 
85  // Check available data
86  if( iBufferDataEnd - iBufferDataStart >= _iSize )
87  return _iSize;
88 
89  // Check available space
90  if( _iSize > iBufferSize )
91  return -EOVERFLOW;
92  if( iBufferSize - iBufferDataEnd < _iSize )
93  flushBuffer();
94 
95  // Receive data
96  double __fdTimeoutStart =
97  ( fdTimeout > 0.0 )
98  ? CData::epoch()
99  : 0.0;
100  do
101  {
102  if( fdTimeout > 0.0 )
103  {
104  if( CData::epoch() - __fdTimeoutStart > fdTimeout )
105  return -ETIMEDOUT;
106  }
107  __iReturn = recv( _iDescriptor,
110  0 );
111  if( __iReturn <= 0 )
112  return __iReturn;
113  iBufferDataEnd += __iReturn;
114  }
115  while( iBufferDataEnd-iBufferDataStart < _iSize );
116 
117  // Done
118  return _iSize;
119 }
120 
121 const unsigned char* CTransmit::pullBuffer( int _iSize )
122 {
123  iBufferDataStart += _iSize;
124  return pucBuffer+(iBufferDataStart-_iSize);
125 }
126 
128 {
129  // Non-overlapping memcpy
130  int __iBufferLength = iBufferDataEnd - iBufferDataStart;
131  int __iBufferCopied = 0;
132  while( __iBufferCopied < __iBufferLength )
133  {
134  int __iBufferCopyLength = __iBufferLength - __iBufferCopied;
135  if( __iBufferCopyLength > iBufferDataStart )
136  __iBufferCopyLength = iBufferDataStart;
137  memcpy( pucBuffer + __iBufferCopied,
138  pucBuffer + __iBufferCopied + iBufferDataStart,
139  __iBufferCopyLength );
140  __iBufferCopied += __iBufferCopyLength;
141  }
143  iBufferDataStart = 0;
144 }
145 
147 {
148  iBufferDataStart = 0;
149  iBufferDataEnd = 0;
150 }
151 
153 {
154  if( poPayload )
155  delete poPayload;
156  poPayload = NULL;
158 }
159 
160 int CTransmit::initPayload( uint8_t _ui8tPayloadType )
161 {
162  // Authorize payload
163  if( CParameters::oPrincipal.hasPayloadTypes()
164  && !CParameters::oPrincipal.hasPayloadType( _ui8tPayloadType ) )
165  return -EPERM;
166 
167  // (Re-)Initialize
168  resetPayload();
169  switch( _ui8tPayloadType )
170  {
171 
172  case PAYLOAD_RAW:
173  poPayload = new CPayload();
174  break;
175 
176  case PAYLOAD_AES128:
177  poPayload = new CPayload_AES128();
178  // ... default key (using user provided password salt)
179  if( pucPasswordSalt )
180  {
181  ((CPayload_AES128*)poPayload)->makeCryptoKey( (unsigned char*)oPrincipal.getPassword(),
182  strlen( oPrincipal.getPassword() ),
183  pucPasswordSalt );
184  }
185  break;
186 
187  default:
188  return -EINVAL;
189  }
190  if( !poPayload )
191  return -ENOMEM;
192  ePayloadType = (EPayloadType)_ui8tPayloadType;
193 
194  // Done
195  return ePayloadType;
196 }
197 
199 {
200  if( !poPayload )
201  return -ENODATA;
202  return poPayload->alloc();
203 }
204 
206 {
207  if( !poPayload )
208  return;
209  poPayload->free();
210 }
211 
212 int CTransmit::serialize( int _iDescriptor,
213  const CData &_roData )
214 {
215  int __iReturn;
216 
217  // Check resources
218  if( !poPayload )
219  return -ENODATA;
220  if( !pucBuffer )
221  {
222  __iReturn = alloc();
223  if( __iReturn < 0 )
224  return __iReturn;
225  }
226 
227  // Create payload
228  __iReturn = poPayload->serialize( pucBuffer, _roData );
229  if( __iReturn < 0 )
230  return __iReturn;
231  int __iPayloadSize = __iReturn;
232 
233  // Send payload
234  uint16_t __ui16tPayloadSize_NS = htons( __iPayloadSize );
235 
236  // ... size
237  __iReturn = send( _iDescriptor, &__ui16tPayloadSize_NS, 2, MSG_MORE );
238  if( __iReturn != 2 )
239  return
240  ( __iReturn <= 0 )
241  ? __iReturn
242  : -EIO;
243 
244  // ... content
245  __iReturn = send( _iDescriptor, pucBuffer, __iPayloadSize, MSG_EOR );
246  if( __iReturn != __iPayloadSize )
247  return
248  ( __iReturn <= 0 )
249  ? __iReturn
250  : -EIO;
251 
252  // Done
253  return __iPayloadSize+2;
254 }
255 
256 int CTransmit::unserialize( int _iDescriptor,
257  CData *_poData,
258  int _iMaxSize )
259 {
260  int __iReturn;
261 
262  // Check resources
263  if( !poPayload )
264  return -ENODATA;
265  if( !pucBuffer )
266  {
267  __iReturn = alloc();
268  if( __iReturn < 0 )
269  return __iReturn;
270  }
271 
272  // Receive payload
273 
274  // ... size
275  __iReturn = recvBuffer( _iDescriptor, 2 );
276  if( __iReturn != 2 )
277  return
278  ( __iReturn <= 0 )
279  ? __iReturn
280  : -EPROTO;
281  uint16_t __ui16tPayloadSize = ntohs( *((uint16_t*)pullBuffer( 2 )) );
282  if( _iMaxSize && __ui16tPayloadSize > _iMaxSize )
283  return -EMSGSIZE;
284 
285  // ... content
286  __iReturn = recvBuffer( _iDescriptor, __ui16tPayloadSize );
287  if( __iReturn != __ui16tPayloadSize )
288  return
289  ( __iReturn <= 0 )
290  ? __iReturn
291  : -EPROTO;
292 
293  // Parse payload
294  __iReturn = poPayload->unserialize( _poData,
295  pullBuffer( __ui16tPayloadSize ),
296  __ui16tPayloadSize );
297  if( __iReturn <= 0 )
298  return __iReturn;
299 
300  // Done
301  return __ui16tPayloadSize+2;
302 }
303 
305 {
306  if( pucBuffer )
307  {
309  pucBuffer = NULL;
310  iBufferSize = 0;
311  iBufferDataStart = 0;
312  iBufferDataEnd = 0;
313  }
314 }
virtual int unserialize(CData *_poData, const unsigned char *_pucBuffer, uint16_t _ui16tBufferSize)
Unserialize the SGCTP data from the given payload buffer.
Definition: payload.cpp:355
virtual int serialize(int _iDescriptor, const CData &_roData)
Serialize the given SGCTP data to the given descriptor.
Definition: transmit.cpp:212
virtual ~CTransmit()
Definition: transmit.cpp:53
const char * getPassword() const
Returns the principal password.
Definition: principal.hpp:118
int iBufferDataEnd
Transmission buffer actual data end offset.
Definition: transmit.hpp:85
static const uint16_t BUFFER_SIZE
Buffer size required for payload (un-)serialization.
Definition: payload.hpp:50
int iBufferSize
Transmission buffer size.
Definition: transmit.hpp:81
virtual int allocPayload()
Allocate resources required for payload (un-)serialization.
Definition: transmit.cpp:198
virtual void free()
Free resources required for data transmission (un-/serialization)
Definition: transmit.cpp:304
static void freeBuffer(unsigned char *_pucBuffer)
Free a buffer allocated for payload (un-)serialization.
Definition: payload.hpp:79
CPrincipal oPrincipal
Principal.
Definition: parameters.hpp:56
virtual int send(int _iDescriptor, const void *_pBuffer, int _iSize, int _iFlags)=0
Send data to the given descriptor.
void flushBuffer()
Flush the data buffer (from pulled data)
Definition: transmit.cpp:127
AES128-encrypted payload.
Definition: transmit.hpp:68
virtual int initPayload(uint8_t _ui8tPayloadType=PAYLOAD_RAW)
Associate and initialize payload object.
Definition: transmit.cpp:160
virtual void free()
Free resources for payload (un-)serialization.
Definition: payload.hpp:168
double fdTimeout
Transmission timeout, in seconds.
Definition: transmit.hpp:88
const unsigned char * pullBuffer(int _iSize)
Pull data from the transmission buffer.
Definition: transmit.cpp:121
int recvBuffer(int _iDescriptor, int _iSize)
Receive data from the given descriptor (and push them on the data buffer)
Definition: transmit.cpp:80
SGCTP data container.
Definition: data.hpp:44
CPayload * poPayload
Associated payload object.
Definition: transmit.hpp:91
virtual int serialize(unsigned char *_pucBuffer, const CData &_roData)
Serialize the given SGCTP data into the given payload buffer.
Definition: payload.cpp:93
EPayloadType ePayloadType
Associated payload type.
Definition: transmit.hpp:93
virtual void resetPayload()
Reset (clear) the associated payload object.
Definition: transmit.cpp:152
virtual int alloc()=0
Allocate resources required for data transmission (un-/serialization)
(Raw) SGCTP payload
Definition: payload.hpp:41
virtual int recv(int _iDescriptor, void *_pBuffer, int _iSize, int _iFlags)=0
Receive data from the given descriptor.
void resetBuffer()
Reset the data buffer (clear all data)
Definition: transmit.cpp:146
virtual int alloc()
Allocate resources for payload (un-)serialization.
Definition: payload.hpp:146
unsigned char * pucBuffer
Transmission buffer.
Definition: transmit.hpp:79
virtual int unserialize(int _iDescriptor, CData *_poData, int _iMaxSize=0)
Unserialize the SGCTP data from the given descriptor.
Definition: transmit.cpp:256
int iBufferDataStart
Transmission buffer actual data start offset.
Definition: transmit.hpp:83
SGCTP transmission/payload parameters.
Definition: parameters.hpp:40
EPayloadType
Payload types.
Definition: transmit.hpp:66
virtual void freePayload()
Free resources required for payload (un-)serialization.
Definition: transmit.cpp:205
const unsigned char * pucPasswordSalt
Cryptographic password salt/nonce (pointer to existing variable)
Definition: parameters.hpp:59
static double epoch()
Return the current (sub-second) UNIX epoch.
Definition: data.cpp:55
AES128-encrypted SGCTP payload.
int allocBuffer()
Allocate resources required for data transmission.
Definition: transmit.cpp:66
static unsigned char * allocBuffer()
Allocate a buffer for payload (un-)serialization.
Definition: payload.hpp:61