Cuberite
A lightweight, fast and extensible game server for Minecraft
TCPLinkImpl.cpp
Go to the documentation of this file.
1 
2 // TCPLinkImpl.cpp
3 
4 // Implements the cTCPLinkImpl class implementing the TCP link functionality
5 
6 #include "Globals.h"
7 #include "TCPLinkImpl.h"
8 #include "../mbedTLS++/SslConfig.h"
9 #include "NetworkSingleton.h"
10 #include "ServerHandleImpl.h"
11 #include "event2/buffer.h"
12 
13 
14 
15 
16 
18 // cTCPLinkImpl:
19 
21  super(a_LinkCallbacks),
22  m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().GetEventBase(), -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS)),
23  m_LocalPort(0),
24  m_RemotePort(0),
25  m_ShouldShutdown(false)
26 {
27 }
28 
29 
30 
31 
32 
33 cTCPLinkImpl::cTCPLinkImpl(evutil_socket_t a_Socket, cTCPLink::cCallbacksPtr a_LinkCallbacks, cServerHandleImplPtr a_Server, const sockaddr * a_Address, socklen_t a_AddrLen):
34  super(a_LinkCallbacks),
35  m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().GetEventBase(), a_Socket, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS)),
36  m_Server(a_Server),
37  m_LocalPort(0),
38  m_RemotePort(0),
39  m_ShouldShutdown(false)
40 {
41  // Update the endpoint addresses:
43  UpdateAddress(a_Address, a_AddrLen, m_RemoteIP, m_RemotePort);
44 }
45 
46 
47 
48 
49 
51 {
52  // If the TLS context still exists, free it:
53  m_TlsContext.reset();
54 
55  bufferevent_free(m_BufferEvent);
56 }
57 
58 
59 
60 
61 
63 {
64  ASSERT(a_LinkCallbacks != nullptr);
65  ASSERT(a_ConnectCallbacks != nullptr);
66 
67  // Create a new link:
68  cTCPLinkImplPtr res{new cTCPLinkImpl(a_LinkCallbacks)}; // Cannot use std::make_shared here, constructor is not accessible
69  res->m_ConnectCallbacks = a_ConnectCallbacks;
71  res->m_Callbacks->OnLinkCreated(res);
72  res->Enable(res);
73 
74  // Callback to connect after performing lookup:
75  class cHostnameCallback :
77  {
78  cTCPLinkImplPtr m_Link;
79  UInt16 m_Port;
80  bool m_IsConnecting;
81 
82  public:
83 
84  cHostnameCallback(cTCPLinkImplPtr a_Link, UInt16 a_ConnectPort):
85  m_Link(std::move(a_Link)),
86  m_Port(a_ConnectPort),
87  m_IsConnecting(false)
88  {
89  }
90 
91  void DoConnect(const sockaddr * a_IP, int size)
92  {
93  // Make sure connect is only completed once
94  if (!m_IsConnecting)
95  {
96  int ErrCode = bufferevent_socket_connect(m_Link->m_BufferEvent, a_IP, size);
97  if (ErrCode == 0)
98  {
99  m_IsConnecting = true;
100  }
101  else
102  {
103  m_Link->GetCallbacks()->OnError(ErrCode, evutil_socket_error_to_string(ErrCode));
104  }
105  }
106  }
107 
108  virtual bool OnNameResolvedV4(const AString & a_Name, const sockaddr_in * a_IP) override
109  {
110  sockaddr_in Addr = *a_IP;
111  Addr.sin_port = htons(m_Port);
112  DoConnect(reinterpret_cast<const sockaddr *>(&Addr), sizeof(Addr));
113  return false; // Don't care about recieving ip as string
114  }
115 
116  virtual bool OnNameResolvedV6(const AString & a_Name, const sockaddr_in6 * a_IP) override
117  {
118  sockaddr_in6 Addr = *a_IP;
119  Addr.sin6_port = htons(m_Port);
120  DoConnect(reinterpret_cast<const sockaddr *>(&Addr), sizeof(Addr));
121  return false; // Don't care about recieving ip as string
122  }
123 
124  virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
125  {
126  m_Link->GetCallbacks()->OnError(a_ErrorCode, a_ErrorMsg);
127  cNetworkSingleton::Get().RemoveLink(m_Link.get());
128  }
129 
130  // Don't need to do anything for these
131  virtual void OnFinished() override
132  {
133  }
134 
135  virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override
136  {
137  }
138  };
139 
140  // Schedule the host query
141  cNetwork::HostnameToIP(a_Host, std::make_shared<cHostnameCallback>(res, a_Port));
142  return res;
143 }
144 
145 
146 
147 
148 
150 {
151  // Take hold of a shared copy of self, to keep as long as the callbacks are coming:
152  m_Self = a_Self;
153 
154  // Set the LibEvent callbacks and enable processing:
155  bufferevent_setcb(m_BufferEvent, ReadCallback, WriteCallback, EventCallback, this);
156  bufferevent_enable(m_BufferEvent, EV_READ | EV_WRITE);
157 }
158 
159 
160 
161 
162 
163 bool cTCPLinkImpl::Send(const void * a_Data, size_t a_Length)
164 {
165  if (m_ShouldShutdown)
166  {
167  LOGD("%s: Cannot send data, the link is already shut down.", __FUNCTION__);
168  return false;
169  }
170 
171  // If running in TLS mode, push the data into the TLS context instead:
172  if (m_TlsContext != nullptr)
173  {
174  m_TlsContext->Send(a_Data, a_Length);
175  return true;
176  }
177 
178  // Send the data:
179  return SendRaw(a_Data, a_Length);
180 }
181 
182 
183 
184 
185 
187 {
188  // If running in TLS mode, notify the TLS layer:
189  if (m_TlsContext != nullptr)
190  {
191  m_TlsContext->NotifyClose();
192  m_TlsContext->ResetSelf();
193  m_TlsContext.reset();
194  }
195 
196  // If there's no outgoing data, shutdown the socket directly:
197  if (evbuffer_get_length(bufferevent_get_output(m_BufferEvent)) == 0)
198  {
200  return;
201  }
202 
203  // There's still outgoing data in the LibEvent buffer, schedule a shutdown when it's written to OS's TCP stack:
204  m_ShouldShutdown = true;
205 }
206 
207 
208 
209 
210 
212 {
213  // If running in TLS mode, notify the TLS layer:
214  if (m_TlsContext != nullptr)
215  {
216  m_TlsContext->NotifyClose();
217  m_TlsContext->ResetSelf();
218  m_TlsContext.reset();
219  }
220 
221  // Disable all events on the socket, but keep it alive:
222  bufferevent_disable(m_BufferEvent, EV_READ | EV_WRITE);
223  if (m_Server == nullptr)
224  {
226  }
227  else
228  {
229  m_Server->RemoveLink(this);
230  }
231  m_Self.reset();
232 }
233 
234 
235 
236 
237 
239  cX509CertPtr a_OwnCert,
240  cCryptoKeyPtr a_OwnPrivKey
241 )
242 {
243  // Check preconditions:
244  if (m_TlsContext != nullptr)
245  {
246  return "TLS is already active on this link";
247  }
248  if ((a_OwnCert == nullptr) != (a_OwnPrivKey == nullptr))
249  {
250  return "Either provide both the certificate and private key, or neither";
251  }
252 
253  // Create the TLS context:
254  m_TlsContext = std::make_shared<cLinkTlsContext>(*this);
255  if (a_OwnCert != nullptr)
256  {
257  auto Config = cSslConfig::MakeDefaultConfig(true);
258  Config->SetOwnCert(std::move(a_OwnCert), std::move(a_OwnPrivKey));
259  m_TlsContext->Initialize(Config);
260  }
261  else
262  {
263  m_TlsContext->Initialize(true);
264  }
265 
267 
268  // Start the handshake:
269  m_TlsContext->Handshake();
270  return {};
271 }
272 
273 
274 
275 
276 
278  cX509CertPtr a_OwnCert,
279  cCryptoKeyPtr a_OwnPrivKey,
280  const AString & a_StartTLSData
281 )
282 {
283  // Check preconditions:
284  if (m_TlsContext != nullptr)
285  {
286  return "TLS is already active on this link";
287  }
288  if ((a_OwnCert == nullptr) || (a_OwnPrivKey == nullptr))
289  {
290  return "Provide the server certificate and private key";
291  }
292 
293  // Create the TLS context:
294  m_TlsContext = std::make_shared<cLinkTlsContext>(*this);
295  {
296  auto Config = cSslConfig::MakeDefaultConfig(false);
297  Config->SetOwnCert(a_OwnCert, a_OwnPrivKey);
298  m_TlsContext->Initialize(std::move(Config));
299  }
301 
302  // Push the initial data:
303  m_TlsContext->StoreReceivedData(a_StartTLSData.data(), a_StartTLSData.size());
304 
305  // Start the handshake:
306  m_TlsContext->Handshake();
307  return {};
308 }
309 
310 
311 
312 
313 
314 void cTCPLinkImpl::ReadCallback(bufferevent * a_BufferEvent, void * a_Self)
315 {
316  ASSERT(a_Self != nullptr);
317  cTCPLinkImpl * Self = static_cast<cTCPLinkImpl *>(a_Self);
318  ASSERT(Self->m_BufferEvent == a_BufferEvent);
319  ASSERT(Self->m_Callbacks != nullptr);
320 
321  // Read all the incoming data, in 1024-byte chunks:
322  char data[1024];
323  size_t length;
324  auto tlsContext = Self->m_TlsContext;
325  while ((length = bufferevent_read(a_BufferEvent, data, sizeof(data))) > 0)
326  {
327  if (tlsContext != nullptr)
328  {
329  ASSERT(tlsContext->IsLink(Self));
330  tlsContext->StoreReceivedData(data, length);
331  }
332  else
333  {
334  Self->ReceivedCleartextData(data, length);
335  }
336  }
337 }
338 
339 
340 
341 
342 
343 void cTCPLinkImpl::WriteCallback(bufferevent * a_BufferEvent, void * a_Self)
344 {
345  ASSERT(a_Self != nullptr);
346  auto Self = static_cast<cTCPLinkImpl *>(a_Self);
347  ASSERT(Self->m_Callbacks != nullptr);
348 
349  // If there's no more data to write and the link has been scheduled for shutdown, do the shutdown:
350  auto OutLen = evbuffer_get_length(bufferevent_get_output(Self->m_BufferEvent));
351  if ((OutLen == 0) && (Self->m_ShouldShutdown))
352  {
353  Self->DoActualShutdown();
354  }
355 }
356 
357 
358 
359 
360 
361 void cTCPLinkImpl::EventCallback(bufferevent * a_BufferEvent, short a_What, void * a_Self)
362 {
363  ASSERT(a_Self != nullptr);
364  cTCPLinkImplPtr Self = static_cast<cTCPLinkImpl *>(a_Self)->m_Self;
365  if (Self == nullptr)
366  {
367  // The link has already been freed
368  return;
369  }
370 
371  // If an error is reported, call the error callback:
372  if (a_What & BEV_EVENT_ERROR)
373  {
374  // Choose the proper callback to call based on whether we were waiting for connection or not:
375  int err = EVUTIL_SOCKET_ERROR();
376  if (Self->m_ConnectCallbacks != nullptr)
377  {
378  if (err == 0)
379  {
380  // This could be a DNS failure
381  err = bufferevent_socket_get_dns_error(a_BufferEvent);
382  }
383  Self->m_ConnectCallbacks->OnError(err, evutil_socket_error_to_string(err));
384  }
385  else
386  {
387  Self->m_Callbacks->OnError(err, evutil_socket_error_to_string(err));
388  if (Self->m_Server == nullptr)
389  {
390  cNetworkSingleton::Get().RemoveLink(Self.get());
391  }
392  else
393  {
394  Self->m_Server->RemoveLink(Self.get());
395  }
396  }
397  Self->m_Self.reset();
398  return;
399  }
400 
401  // Pending connection succeeded, call the connection callback:
402  if (a_What & BEV_EVENT_CONNECTED)
403  {
404  Self->UpdateLocalAddress();
405  Self->UpdateRemoteAddress();
406  if (Self->m_ConnectCallbacks != nullptr)
407  {
408  Self->m_ConnectCallbacks->OnConnected(*Self);
409  // Reset the connect callbacks so that later errors get reported through the link callbacks:
410  Self->m_ConnectCallbacks.reset();
411  return;
412  }
413  }
414 
415  // If the connection has been closed, call the link callback and remove the connection:
416  if (a_What & BEV_EVENT_EOF)
417  {
418  // If running in TLS mode and there's data left in the TLS contect, report it:
419  auto tlsContext = Self->m_TlsContext;
420  if (tlsContext != nullptr)
421  {
422  tlsContext->FlushBuffers();
423  }
424 
425  Self->m_Callbacks->OnRemoteClosed();
426  if (Self->m_Server != nullptr)
427  {
428  Self->m_Server->RemoveLink(Self.get());
429  }
430  else
431  {
432  cNetworkSingleton::Get().RemoveLink(Self.get());
433  }
434  Self->m_Self.reset();
435  return;
436  }
437 
438  // Unknown event, report it:
439  LOGWARNING("cTCPLinkImpl: Unhandled LibEvent event %d (0x%x)", a_What, a_What);
440  ASSERT(!"cTCPLinkImpl: Unhandled LibEvent event");
441 }
442 
443 
444 
445 
446 
447 void cTCPLinkImpl::UpdateAddress(const sockaddr * a_Address, socklen_t a_AddrLen, AString & a_IP, UInt16 & a_Port)
448 {
449  // Based on the family specified in the address, use the correct datastructure to convert to IP string:
450  char IP[128];
451  switch (a_Address->sa_family)
452  {
453  case AF_INET: // IPv4:
454  {
455  const sockaddr_in * sin = reinterpret_cast<const sockaddr_in *>(a_Address);
456  evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP));
457  a_Port = ntohs(sin->sin_port);
458  break;
459  }
460  case AF_INET6: // IPv6
461  {
462  const sockaddr_in6 * sin = reinterpret_cast<const sockaddr_in6 *>(a_Address);
463  evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP));
464  a_Port = ntohs(sin->sin6_port);
465  break;
466  }
467 
468  default:
469  {
470  LOGWARNING("%s: Unknown socket address family: %d", __FUNCTION__, a_Address->sa_family);
471  ASSERT(!"Unknown socket address family");
472  break;
473  }
474  }
475  a_IP.assign(IP);
476 }
477 
478 
479 
480 
481 
483 {
484  sockaddr_storage sa;
485  socklen_t salen = static_cast<socklen_t>(sizeof(sa));
486  getsockname(bufferevent_getfd(m_BufferEvent), reinterpret_cast<sockaddr *>(&sa), &salen);
487  UpdateAddress(reinterpret_cast<const sockaddr *>(&sa), salen, m_LocalIP, m_LocalPort);
488 }
489 
490 
491 
492 
493 
495 {
496  sockaddr_storage sa;
497  socklen_t salen = static_cast<socklen_t>(sizeof(sa));
498  getpeername(bufferevent_getfd(m_BufferEvent), reinterpret_cast<sockaddr *>(&sa), &salen);
499  UpdateAddress(reinterpret_cast<const sockaddr *>(&sa), salen, m_RemoteIP, m_RemotePort);
500 }
501 
502 
503 
504 
505 
507 {
508  #ifdef _WIN32
509  shutdown(bufferevent_getfd(m_BufferEvent), SD_SEND);
510  #else
511  shutdown(bufferevent_getfd(m_BufferEvent), SHUT_WR);
512  #endif
513  bufferevent_disable(m_BufferEvent, EV_WRITE);
514 }
515 
516 
517 
518 
519 
520 bool cTCPLinkImpl::SendRaw(const void * a_Data, size_t a_Length)
521 {
522  return (bufferevent_write(m_BufferEvent, a_Data, a_Length) == 0);
523 }
524 
525 
526 
527 
528 
529 void cTCPLinkImpl::ReceivedCleartextData(const char * a_Data, size_t a_Length)
530 {
531  ASSERT(m_Callbacks != nullptr);
532  m_Callbacks->OnReceivedData(a_Data, a_Length);
533 }
534 
535 
536 
537 
538 
540 // cTCPLinkImpl::cLinkTlsContext:
541 
543  m_Link(a_Link)
544 {
545 }
546 
547 
548 
549 
550 
552 {
553  m_Self = a_Self;
554 }
555 
556 
557 
558 
559 
561 {
562  m_Self.reset();
563 }
564 
565 
566 
567 
568 
569 void cTCPLinkImpl::cLinkTlsContext::StoreReceivedData(const char * a_Data, size_t a_NumBytes)
570 {
571  // Hold self alive for the duration of this function
573 
574  m_EncryptedData.append(a_Data, a_NumBytes);
575 
576  // Try to finish a pending handshake:
578 
579  // Flush any cleartext data that can be "received":
580  FlushBuffers();
581 }
582 
583 
584 
585 
586 
588 {
589  // Hold self alive for the duration of this function
591 
592  // If the handshake didn't complete yet, bail out:
593  if (!HasHandshaken())
594  {
595  return;
596  }
597 
598  char Buffer[1024];
599  int NumBytes;
600  while ((NumBytes = ReadPlain(Buffer, sizeof(Buffer))) > 0)
601  {
602  m_Link.ReceivedCleartextData(Buffer, static_cast<size_t>(NumBytes));
603  if (m_Self.expired())
604  {
605  // The callback closed the SSL context, bail out
606  return;
607  }
608  }
609 }
610 
611 
612 
613 
614 
616 {
617  // Hold self alive for the duration of this function
619 
620  // If the handshake hasn't finished yet, retry:
621  if (!HasHandshaken())
622  {
623  Handshake();
624  // If the handshake succeeded, write all the queued plaintext data:
625  if (HasHandshaken())
626  {
627  m_Link.GetCallbacks()->OnTlsHandshakeCompleted();
628  WritePlain(m_CleartextData.data(), m_CleartextData.size());
629  m_CleartextData.clear();
630  }
631  }
632 }
633 
634 
635 
636 
637 
638 void cTCPLinkImpl::cLinkTlsContext::Send(const void * a_Data, size_t a_Length)
639 {
640  // Hold self alive for the duration of this function
642 
643  // If the handshake hasn't completed yet, queue the data:
644  if (!HasHandshaken())
645  {
646  m_CleartextData.append(reinterpret_cast<const char *>(a_Data), a_Length);
648  return;
649  }
650 
651  // The connection is all set up, write the cleartext data into the SSL context:
652  WritePlain(a_Data, a_Length);
653  FlushBuffers();
654 }
655 
656 
657 
658 
659 
660 int cTCPLinkImpl::cLinkTlsContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes)
661 {
662  // Hold self alive for the duration of this function
664 
665  // If there's nothing queued in the buffer, report empty buffer:
666  if (m_EncryptedData.empty())
667  {
668  return MBEDTLS_ERR_SSL_WANT_READ;
669  }
670 
671  // Copy as much data as possible to the provided buffer:
672  size_t BytesToCopy = std::min(a_NumBytes, m_EncryptedData.size());
673  memcpy(a_Buffer, m_EncryptedData.data(), BytesToCopy);
674  m_EncryptedData.erase(0, BytesToCopy);
675  return static_cast<int>(BytesToCopy);
676 }
677 
678 
679 
680 
681 
682 int cTCPLinkImpl::cLinkTlsContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes)
683 {
684  m_Link.SendRaw(a_Buffer, a_NumBytes);
685  return static_cast<int>(a_NumBytes);
686 }
687 
688 
689 
690 
691 
693 // cNetwork API:
694 
696  const AString & a_Host,
697  UInt16 a_Port,
698  cNetwork::cConnectCallbacksPtr a_ConnectCallbacks,
699  cTCPLink::cCallbacksPtr a_LinkCallbacks
700 )
701 {
702  // Add a connection request to the queue:
703  cTCPLinkImplPtr Conn = cTCPLinkImpl::Connect(a_Host, a_Port, a_LinkCallbacks, a_ConnectCallbacks);
704  return (Conn != nullptr);
705 }
706 
707 
708 
709 
710 
void FlushBuffers(void)
Tries to read any cleartext data available through the SSL, reports it in the link.
virtual int SendEncrypted(const unsigned char *a_Buffer, size_t a_NumBytes) override
void RemoveLink(const cTCPLink *a_Link)
Removes the specified link from m_Connections.
static void UpdateAddress(const sockaddr *a_Address, socklen_t a_AddrLen, AString &a_IP, UInt16 &a_Port)
Sets a_IP and a_Port to values read from a_Address, based on the correct address family.
virtual AString StartTLSServer(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, const AString &a_StartTLSData) override
Starts a TLS handshake as a server connection.
static bool Connect(const AString &a_Host, UInt16 a_Port, cConnectCallbacksPtr a_ConnectCallbacks, cTCPLink::cCallbacksPtr a_LinkCallbacks)
Queues a TCP connection to be made to the specified host.
void TryFinishHandshaking(void)
Tries to finish handshaking the SSL.
cServerHandleImplPtr m_Server
The server handle that has created this link.
Definition: TCPLinkImpl.h:144
std::shared_ptr< cX509Cert > cX509CertPtr
Definition: SslConfig.h:13
bool m_ShouldShutdown
If true, Shutdown() has been called and is in queue.
Definition: TCPLinkImpl.h:165
void UpdateRemoteAddress(void)
Updates m_RemoteIP and m_RemotePort based on the metadata read from the socket.
Callbacks used when resolving names to IPs.
Definition: Network.h:268
std::shared_ptr< cCryptoKey > cCryptoKeyPtr
Definition: CryptoKey.h:72
cTCPLinkImplPtr m_Self
SharedPtr to self, used to keep this object alive as long as the callbacks are coming.
Definition: TCPLinkImpl.h:160
AString m_LocalIP
The IP address of the local endpoint.
Definition: TCPLinkImpl.h:147
cLinkTlsContextWPtr m_Self
Shared ownership of self, so that this object can keep itself alive for as long as it needs...
Definition: TCPLinkImpl.h:98
cLinkTlsContext(cTCPLinkImpl &a_Link)
cTCPLinkImpl(evutil_socket_t a_Socket, cCallbacksPtr a_LinkCallbacks, cServerHandleImplPtr a_Server, const sockaddr *a_Address, socklen_t a_AddrLen)
Creates a new link based on the given socket.
Definition: TCPLinkImpl.cpp:33
virtual AString StartTLSClient(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey) override
Starts a TLS handshake as a client connection.
AString m_EncryptedData
Buffer for storing the incoming encrypted data until it is requested by the SSL decryptor.
Definition: TCPLinkImpl.h:92
std::shared_ptr< cLinkTlsContext > cLinkTlsContextPtr
Definition: TCPLinkImpl.h:81
static std::shared_ptr< cSslConfig > MakeDefaultConfig(bool a_IsClient)
Creates a new config with some sensible defaults on top of mbedTLS basic settings.
Definition: SslConfig.cpp:226
virtual void Close(void) override
Drops the connection without any more processing.
static void EventCallback(bufferevent *a_BufferEvent, short a_What, void *a_Self)
Callback that LibEvent calls when there&#39;s a non-data-related event on the socket. ...
static void ReadCallback(bufferevent *a_BufferEvent, void *a_Self)
Callback that LibEvent calls when there&#39;s data available from the remote peer.
virtual ~cTCPLinkImpl() override
Destroys the LibEvent handle representing the link.
Definition: TCPLinkImpl.cpp:50
static bool HostnameToIP(const AString &a_Hostname, cResolveNameCallbacksPtr a_Callbacks)
Queues a DNS query to resolve the specified hostname to IP address.
cCallbacksPtr m_Callbacks
Callbacks to be used for the various situations.
Definition: Network.h:130
std::shared_ptr< cTCPLinkImpl > cTCPLinkImplPtr
void Send(const void *a_Data, size_t a_Length)
Sends the specified cleartext data over the SSL to the remote peer.
UInt16 m_LocalPort
The port of the local endpoint.
Definition: TCPLinkImpl.h:150
void StoreReceivedData(const char *a_Data, size_t a_NumBytes)
Stores the specified block of data into the buffer of the data to be decrypted (incoming from remote)...
void ReceivedCleartextData(const char *a_Data, size_t a_Length)
Called by the TLS when it has decoded a piece of incoming cleartext data from the socket...
void UpdateLocalAddress(void)
Updates m_LocalIP and m_LocalPort based on the metadata read from the socket.
bufferevent * m_BufferEvent
The LibEvent handle representing this connection.
Definition: TCPLinkImpl.h:140
void DoActualShutdown(void)
Calls shutdown on the link and disables LibEvent writing.
AString m_RemoteIP
The IP address of the remote endpoint.
Definition: TCPLinkImpl.h:153
#define ASSERT(x)
Definition: Globals.h:335
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
#define LOGD(...)
Definition: LoggerSimple.h:40
std::shared_ptr< cServerHandleImpl > cServerHandleImplPtr
static void WriteCallback(bufferevent *a_BufferEvent, void *a_Self)
Callback that LibEvent calls when the remote peer can receive more data.
void AddLink(cTCPLinkPtr a_Link)
Adds the specified link to m_Connections.
static cTCPLinkImplPtr Connect(const AString &a_Host, UInt16 a_Port, cTCPLink::cCallbacksPtr a_LinkCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks)
Queues a connection request to the specified host.
Definition: TCPLinkImpl.cpp:62
unsigned short UInt16
Definition: Globals.h:114
std::shared_ptr< cCallbacks > cCallbacksPtr
Definition: Network.h:63
std::weak_ptr< cLinkTlsContext > cLinkTlsContextWPtr
Definition: TCPLinkImpl.h:83
std::string AString
Definition: StringUtils.h:13
static cNetworkSingleton & Get(void)
Returns the singleton instance of this class.
cLinkTlsContextPtr m_TlsContext
The SSL context used for encryption, if this link uses SSL.
Definition: TCPLinkImpl.h:169
std::shared_ptr< cConnectCallbacks > cConnectCallbacksPtr
Definition: Network.h:240
Interface that provides the methods available on a single TCP connection.
Definition: Network.h:33
void Enable(cTCPLinkImplPtr a_Self)
Enables communication over the link.
virtual bool Send(const void *a_Data, size_t a_Length) override
Queues the specified data for sending to the remote peer.
bool SendRaw(const void *a_Data, size_t a_Length)
Sends the data directly to the socket (without the optional TLS).
void SetSelf(cLinkTlsContextWPtr a_Self)
Shares ownership of self, so that this object can keep itself alive for as long as it needs...
virtual int ReceiveEncrypted(unsigned char *a_Buffer, size_t a_NumBytes) override
void ResetSelf(void)
Removes the self ownership so that we can detect the SSL closure.
virtual void Shutdown(void) override
Closes the link gracefully.
AString m_CleartextData
Buffer for storing the outgoing cleartext data until the link has finished handshaking.
Definition: TCPLinkImpl.h:95
UInt16 m_RemotePort
The port of the remote endpoint.
Definition: TCPLinkImpl.h:156
cCallbacksPtr GetCallbacks(void) const
Returns the callbacks that are used.
Definition: Network.h:126