Cuberite
A lightweight, fast and extensible game server for Minecraft
ManualBindings_Network.cpp
Go to the documentation of this file.
1 
2 // ManualBindings_Network.cpp
3 
4 // Implements the cNetwork-related API bindings for Lua
5 // Also implements the cUrlClient bindings
6 
7 #include "Globals.h"
8 #include "ManualBindings.h"
9 #include "tolua++/include/tolua++.h"
10 #include "LuaState.h"
11 #include "LuaTCPLink.h"
12 #include "LuaNameLookup.h"
13 #include "LuaServerHandle.h"
14 #include "LuaUDPEndpoint.h"
15 #include "../HTTP/UrlClient.h"
16 
17 
18 
19 
20 
22 // cNetwork API functions:
23 
25 static int tolua_cNetwork_Connect(lua_State * L)
26 {
27  // Function signature:
28  // cNetwork:Connect(Host, Port, Callbacks) -> bool
29 
30  cLuaState S(L);
31  if (
32  !S.CheckParamStaticSelf("cNetwork") ||
33  !S.CheckParamString(2) ||
34  !S.CheckParamNumber(3) ||
35  !S.CheckParamTable(4) ||
36  !S.CheckParamEnd(5)
37  )
38  {
39  return 0;
40  }
41 
42  // Read the params:
43  AString host;
44  int port = 0;
45  cLuaState::cTableRefPtr callbacks;
46  if (!S.GetStackValues(2, host, port, callbacks))
47  {
48  return S.ApiParamError("Cannot read parameters.");
49  }
50 
51  // Check validity:
52  if ((port < 0) || (port > 65535))
53  {
54  return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), port));
55  }
56  ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false
57 
58  // Create the LuaTCPLink glue class:
59  auto link = std::make_shared<cLuaTCPLink>(std::move(callbacks));
60 
61  // Try to connect:
62  bool res = cNetwork::Connect(host, static_cast<UInt16>(port), link, link);
63  S.Push(res);
64 
65  return 1;
66 }
67 
68 
69 
70 
71 
73 static int tolua_cNetwork_CreateUDPEndpoint(lua_State * L)
74 {
75  // Function signature:
76  // cNetwork:CreateUDPEndpoint(Port, Callbacks) -> cUDPEndpoint
77 
78  cLuaState S(L);
79  if (
80  !S.CheckParamStaticSelf("cNetwork") ||
81  !S.CheckParamNumber(2) ||
82  !S.CheckParamTable(3) ||
83  !S.CheckParamEnd(4)
84  )
85  {
86  return 0;
87  }
88 
89  // Read the params:
90  int port;
91  cLuaState::cTableRefPtr callbacks;
92  if (!S.GetStackValues(2, port, callbacks))
93  {
94  return S.ApiParamError("Cannot read parameters");
95  }
96 
97  // Check validity:
98  if ((port < 0) || (port > 65535))
99  {
100  return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), port));
101  }
102  ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false
103 
104  // Create the LuaUDPEndpoint glue class:
105  auto endpoint = std::make_shared<cLuaUDPEndpoint>(std::move(callbacks));
106  endpoint->Open(static_cast<UInt16>(port), endpoint);
107 
108  // Register the endpoint to be garbage-collected by Lua:
109  tolua_pushusertype(L, endpoint.get(), "cUDPEndpoint");
110  tolua_register_gc(L, lua_gettop(L));
111 
112  // Return the endpoint object:
113  S.Push(endpoint.get());
114  return 1;
115 }
116 
117 
118 
119 
120 
122 static int tolua_cNetwork_EnumLocalIPAddresses(lua_State * L)
123 {
124  // Function signature:
125  // cNetwork:EnumLocalIPAddresses() -> {string, ...}
126 
127  cLuaState S(L);
128  if (
129  !S.CheckParamStaticSelf("cNetwork") ||
130  !S.CheckParamEnd(2)
131  )
132  {
133  return 0;
134  }
135 
136  // Push the enumerated addresses:
138  return 1;
139 }
140 
141 
142 
143 
144 
146 static int tolua_cNetwork_HostnameToIP(lua_State * L)
147 {
148  // Function signature:
149  // cNetwork:HostnameToIP(Host, Callbacks) -> bool
150 
151  cLuaState S(L);
152  if (
153  !S.CheckParamStaticSelf("cNetwork") ||
154  !S.CheckParamString(2) ||
155  !S.CheckParamTable(3) ||
156  !S.CheckParamEnd(4)
157  )
158  {
159  return 0;
160  }
161 
162  // Read the params:
163  AString host;
164  cLuaState::cTableRefPtr callbacks;
165  if (!S.GetStackValues(2, host, callbacks))
166  {
167  return S.ApiParamError("Cannot read parameters.");
168  }
169  ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false
170 
171  // Try to look up:
172  bool res = cNetwork::HostnameToIP(host, std::make_shared<cLuaNameLookup>(host, std::move(callbacks)));
173  S.Push(res);
174  return 1;
175 }
176 
177 
178 
179 
180 
182 static int tolua_cNetwork_IPToHostname(lua_State * L)
183 {
184  // Function signature:
185  // cNetwork:IPToHostname(IP, Callbacks) -> bool
186 
187  cLuaState S(L);
188  if (
189  !S.CheckParamStaticSelf("cNetwork") ||
190  !S.CheckParamString(2) ||
191  !S.CheckParamTable(3) ||
192  !S.CheckParamEnd(4)
193  )
194  {
195  return 0;
196  }
197 
198  // Read the params:
199  AString ip;
200  cLuaState::cTableRefPtr callbacks;
201  if (!S.GetStackValues(2, ip, callbacks))
202  {
203  return S.ApiParamError("Cannot read parameters.");
204  }
205  ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false
206 
207  // Try to look up:
208  bool res = cNetwork::IPToHostName(ip, std::make_shared<cLuaNameLookup>(ip, std::move(callbacks)));
209  S.Push(res);
210  return 1;
211 }
212 
213 
214 
215 
216 
218 static int tolua_cNetwork_Listen(lua_State * L)
219 {
220  // Function signature:
221  // cNetwork:Listen(Port, Callbacks) -> cServerHandle
222 
223  cLuaState S(L);
224  if (
225  !S.CheckParamStaticSelf("cNetwork") ||
226  !S.CheckParamNumber(2) ||
227  !S.CheckParamTable(3) ||
228  !S.CheckParamEnd(4)
229  )
230  {
231  return 0;
232  }
233 
234  // Read the params:
235  int port = 0;
236  cLuaState::cTableRefPtr callbacks;
237  if (!S.GetStackValues(2, port, callbacks))
238  {
239  return S.ApiParamError("Cannot read parameters");
240  }
241 
242  // Check the validity:
243  if ((port < 0) || (port > 65535))
244  {
245  return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), port));
246  }
247  auto port16 = static_cast<UInt16>(port);
248 
249  // Create the LuaTCPLink glue class:
250  auto srv = std::make_shared<cLuaServerHandle>(port16, std::move(callbacks));
251 
252  // Listen:
253  srv->SetServerHandle(cNetwork::Listen(port16, srv), srv);
254 
255  // Register the server to be garbage-collected by Lua:
256  tolua_pushusertype(L, srv.get(), "cServerHandle");
257  tolua_register_gc(L, lua_gettop(L));
258 
259  // Return the server handle wrapper:
260  S.Push(srv.get());
261  return 1;
262 }
263 
264 
265 
266 
267 
269 // cServerHandle bindings (routed through cLuaServerHandle):
270 
273 static int tolua_collect_cServerHandle(lua_State * L)
274 {
275  auto Srv = static_cast<cLuaServerHandle *>(tolua_tousertype(L, 1, nullptr));
276  ASSERT(Srv != nullptr);
277  Srv->Release();
278  return 0;
279 }
280 
281 
282 
283 
284 
286 static int tolua_cServerHandle_Close(lua_State * L)
287 {
288  // Function signature:
289  // ServerInstance:Close()
290 
291  cLuaState S(L);
292  if (
293  !S.CheckParamSelf("cServerHandle") ||
294  !S.CheckParamEnd(2)
295  )
296  {
297  return 0;
298  }
299 
300  // Get the server handle:
301  auto Srv = *static_cast<cLuaServerHandle **>(lua_touserdata(L, 1));
302  ASSERT(Srv != nullptr); // Checked by CheckParamSelf()
303 
304  // Close it:
305  Srv->Close();
306  return 0;
307 }
308 
309 
310 
311 
312 
314 static int tolua_cServerHandle_IsListening(lua_State * L)
315 {
316  // Function signature:
317  // ServerInstance:IsListening() -> bool
318 
319  cLuaState S(L);
320  if (
321  !S.CheckParamSelf("cServerHandle") ||
322  !S.CheckParamEnd(2)
323  )
324  {
325  return 0;
326  }
327 
328  // Get the server handle:
329  auto Srv = *static_cast<cLuaServerHandle **>(lua_touserdata(L, 1));
330  ASSERT(Srv != nullptr); // Checked by CheckParamSelf()
331 
332  // Query it:
333  S.Push(Srv->IsListening());
334  return 1;
335 }
336 
337 
338 
339 
340 
342 // cTCPLink bindings (routed through cLuaTCPLink):
343 
345 static int tolua_cTCPLink_Close(lua_State * L)
346 {
347  // Function signature:
348  // LinkInstance:Close()
349 
350  cLuaState S(L);
351  if (
352  !S.CheckParamSelf("cTCPLink") ||
353  !S.CheckParamEnd(2)
354  )
355  {
356  return 0;
357  }
358 
359  // Get the link:
360  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
361  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
362 
363  // Close the link:
364  Link->Close();
365  return 0;
366 }
367 
368 
369 
370 
371 
373 static int tolua_cTCPLink_GetLocalIP(lua_State * L)
374 {
375  // Function signature:
376  // LinkInstance:GetLocalIP() -> string
377 
378  cLuaState S(L);
379  if (
380  !S.CheckParamSelf("cTCPLink") ||
381  !S.CheckParamEnd(2)
382  )
383  {
384  return 0;
385  }
386 
387  // Get the link:
388  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
389  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
390 
391  // Get the IP:
392  S.Push(Link->GetLocalIP());
393  return 1;
394 }
395 
396 
397 
398 
399 
401 static int tolua_cTCPLink_GetLocalPort(lua_State * L)
402 {
403  // Function signature:
404  // LinkInstance:GetLocalPort() -> number
405 
406  cLuaState S(L);
407  if (
408  !S.CheckParamSelf("cTCPLink") ||
409  !S.CheckParamEnd(2)
410  )
411  {
412  return 0;
413  }
414 
415  // Get the link:
416  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
417  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
418 
419  // Get the Port:
420  S.Push(Link->GetLocalPort());
421  return 1;
422 }
423 
424 
425 
426 
427 
429 static int tolua_cTCPLink_GetRemoteIP(lua_State * L)
430 {
431  // Function signature:
432  // LinkInstance:GetRemoteIP() -> string
433 
434  cLuaState S(L);
435  if (
436  !S.CheckParamSelf("cTCPLink") ||
437  !S.CheckParamEnd(2)
438  )
439  {
440  return 0;
441  }
442 
443  // Get the link:
444  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
445  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
446 
447  // Get the IP:
448  S.Push(Link->GetRemoteIP());
449  return 1;
450 }
451 
452 
453 
454 
455 
457 static int tolua_cTCPLink_GetRemotePort(lua_State * L)
458 {
459  // Function signature:
460  // LinkInstance:GetRemotePort() -> number
461 
462  cLuaState S(L);
463  if (
464  !S.CheckParamSelf("cTCPLink") ||
465  !S.CheckParamEnd(2)
466  )
467  {
468  return 0;
469  }
470 
471  // Get the link:
472  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
473  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
474 
475  // Get the Port:
476  S.Push(Link->GetRemotePort());
477  return 1;
478 }
479 
480 
481 
482 
483 
485 static int tolua_cTCPLink_Send(lua_State * L)
486 {
487  // Function signature:
488  // LinkInstance:Send(DataString)
489 
490  cLuaState S(L);
491  if (
492  !S.CheckParamSelf("cTCPLink") ||
493  !S.CheckParamString(2) ||
494  !S.CheckParamEnd(3)
495  )
496  {
497  return 0;
498  }
499 
500  // Get the link:
501  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
502  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
503 
504  // Get the data to send:
505  AString Data;
506  S.GetStackValues(2, Data);
507 
508  // Send the data:
509  Link->Send(Data);
510  return 0;
511 }
512 
513 
514 
515 
516 
518 static int tolua_cTCPLink_Shutdown(lua_State * L)
519 {
520  // Function signature:
521  // LinkInstance:Shutdown()
522 
523  cLuaState S(L);
524  if (
525  !S.CheckParamSelf("cTCPLink") ||
526  !S.CheckParamEnd(2)
527  )
528  {
529  return 0;
530  }
531 
532  // Get the link:
533  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
534  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
535 
536  // Shutdown the link:
537  Link->Shutdown();
538  return 0;
539 }
540 
541 
542 
543 
544 
546 static int tolua_cTCPLink_StartTLSClient(lua_State * L)
547 {
548  // Function signature:
549  // LinkInstance:StartTLSClient(OwnCert, OwnPrivKey, OwnPrivKeyPassword, TrustedRootCAs) -> [true] or [nil, ErrMsg]
550 
551  // Get the link:
552  cLuaState S(L);
553  if (!S.CheckParamSelf("cTCPLink"))
554  {
555  return 0;
556  }
557  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
558  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
559 
560  // Read the (optional) params:
561  AString OwnCert, OwnPrivKey, OwnPrivKeyPassword, TrustedRootCAs;
562  S.GetStackValues(2, OwnCert, OwnPrivKey, OwnPrivKeyPassword, cLuaState::cOptionalParam<std::string>(TrustedRootCAs));
563 
564  // Start the TLS handshake:
565  AString res = Link->StartTLSClient(OwnCert, OwnPrivKey, OwnPrivKeyPassword, TrustedRootCAs);
566  if (!res.empty())
567  {
568  S.Push(cLuaState::Nil, fmt::format(
569  FMT_STRING("Cannot start TLS on link to {}:{}: {}"),
570  Link->GetRemoteIP(), Link->GetRemotePort(), res
571  ));
572  return 2;
573  }
574  return 1;
575 }
576 
577 
578 
579 
580 
582 static int tolua_cTCPLink_StartTLSServer(lua_State * L)
583 {
584  // Function signature:
585  // LinkInstance:StartTLSServer(OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData) -> [true] or [nil, ErrMsg]
586 
587  cLuaState S(L);
588  if (
589  !S.CheckParamSelf("cTCPLink") ||
590  !S.CheckParamString(2, 4) ||
591  // Param 5 is optional, don't check
592  !S.CheckParamEnd(6)
593  )
594  {
595  return 0;
596  }
597 
598  // Get the link:
599  auto Link = *static_cast<cLuaTCPLink **>(lua_touserdata(L, 1));
600  ASSERT(Link != nullptr); // Checked by CheckParamSelf()
601 
602  // Read the params:
603  AString OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData;
604  S.GetStackValues(2, OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData);
605 
606  // Start the TLS handshake:
607  AString res = Link->StartTLSServer(OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData);
608  if (!res.empty())
609  {
610  S.Push(cLuaState::Nil, fmt::format(
611  FMT_STRING("Cannot start TLS on link to {}:{}: {}"),
612  Link->GetRemoteIP(), Link->GetRemotePort(), res
613  ));
614  return 2;
615  }
616  S.Push(true);
617  return 1;
618 }
619 
620 
621 
622 
623 
625 // cUDPEndpoint bindings (routed through cLuaUDPEndpoint):
626 
629 static int tolua_collect_cUDPEndpoint(lua_State * L)
630 {
631  auto endpoint = static_cast<cLuaUDPEndpoint *>(tolua_tousertype(L, 1, nullptr));
632  ASSERT(endpoint != nullptr);
633  endpoint->Release();
634  return 0;
635 }
636 
637 
638 
639 
640 
642 static int tolua_cUDPEndpoint_Close(lua_State * L)
643 {
644  // Function signature:
645  // EndpointInstance:Close()
646 
647  cLuaState S(L);
648  if (
649  !S.CheckParamSelf("cUDPEndpoint") ||
650  !S.CheckParamEnd(2)
651  )
652  {
653  return 0;
654  }
655 
656  // Get the endpoint:
657  auto endpoint = *static_cast<cLuaUDPEndpoint **>(lua_touserdata(L, 1));
658  ASSERT(endpoint != nullptr);
659 
660  // Close it:
661  endpoint->Close();
662  return 0;
663 }
664 
665 
666 
667 
668 
670 static int tolua_cUDPEndpoint_EnableBroadcasts(lua_State * L)
671 {
672  // Function signature:
673  // EndpointInstance:EnableBroadcasts()
674 
675  cLuaState S(L);
676  if (
677  !S.CheckParamSelf("cUDPEndpoint") ||
678  !S.CheckParamEnd(2)
679  )
680  {
681  return 0;
682  }
683 
684  // Get the endpoint:
685  auto endpoint = *static_cast<cLuaUDPEndpoint **>(lua_touserdata(L, 1));
686  ASSERT(endpoint != nullptr);
687 
688  // Enable the broadcasts:
689  endpoint->EnableBroadcasts();
690  return 0;
691 }
692 
693 
694 
695 
696 
698 static int tolua_cUDPEndpoint_GetPort(lua_State * L)
699 {
700  // Function signature:
701  // Endpoint:GetPort() -> number
702 
703  cLuaState S(L);
704  if (
705  !S.CheckParamSelf("cUDPEndpoint") ||
706  !S.CheckParamEnd(2)
707  )
708  {
709  return 0;
710  }
711 
712  // Get the endpoint:
713  auto endpoint = *static_cast<cLuaUDPEndpoint **>(lua_touserdata(L, 1));
714  ASSERT(endpoint != nullptr);
715 
716  // Get the Port:
717  S.Push(endpoint->GetPort());
718  return 1;
719 }
720 
721 
722 
723 
724 
726 static int tolua_cUDPEndpoint_IsOpen(lua_State * L)
727 {
728  // Function signature:
729  // Endpoint:IsOpen() -> bool
730 
731  cLuaState S(L);
732  if (
733  !S.CheckParamSelf("cUDPEndpoint") ||
734  !S.CheckParamEnd(2)
735  )
736  {
737  return 0;
738  }
739 
740  // Get the endpoint:
741  auto endpoint = *static_cast<cLuaUDPEndpoint **>(lua_touserdata(L, 1));
742  ASSERT(endpoint != nullptr);
743 
744  // Close it:
745  S.Push(endpoint->IsOpen());
746  return 1;
747 }
748 
749 
750 
751 
752 
754 static int tolua_cUDPEndpoint_Send(lua_State * L)
755 {
756  // Function signature:
757  // Endpoint:Send(DataString)
758 
759  cLuaState S(L);
760  if (
761  !S.CheckParamSelf("cUDPEndpoint") ||
762  !S.CheckParamString(2, 3) ||
763  !S.CheckParamNumber(4) ||
764  !S.CheckParamEnd(5)
765  )
766  {
767  return 0;
768  }
769 
770  // Get the link:
771  auto endpoint = *static_cast<cLuaUDPEndpoint **>(lua_touserdata(L, 1));
772  ASSERT(endpoint != nullptr);
773 
774  // Get the data to send:
775  AString data, remotePeer;
776  int remotePort = 0;
777  S.GetStackValues(2, data, remotePeer, remotePort);
778 
779  // Check the port:
780  if ((remotePort < 0) || (remotePort > USHRT_MAX))
781  {
782  return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), remotePort));
783  }
784 
785  // Send the data:
786  S.Push(endpoint->Send(data, remotePeer, static_cast<UInt16>(remotePort)));
787  return 1;
788 }
789 
790 
791 
792 
793 
798 {
799 public:
802  m_Callbacks(std::move(a_Callbacks))
803  {
804  }
805 
806 
807  // cUrlClient::cCallbacks overrides:
808  virtual void OnConnected(cTCPLink & a_Link) override
809  {
810  // TODO: Cannot push a cTCPLink to Lua, need to translate via cLuaTCPLink
811  m_Callbacks->CallTableFnWithSelf("OnConnected", cLuaState::Nil, a_Link.GetRemoteIP(), a_Link.GetRemotePort());
812  }
813 
814 
815  virtual bool OnCertificateReceived() override
816  {
817  // TODO: The received cert needs proper type specification from the underlying cUrlClient framework and in the Lua engine as well
818  bool res = true;
819  m_Callbacks->CallTableFnWithSelf("OnCertificateReceived", cLuaState::Return, res);
820  return res;
821  }
822 
823 
824  virtual void OnTlsHandshakeCompleted() override
825  {
826  m_Callbacks->CallTableFnWithSelf("OnTlsHandshakeCompleted");
827  }
828 
829 
830  virtual void OnRequestSent() override
831  {
832  m_Callbacks->CallTableFnWithSelf("OnRequestSent");
833  }
834 
835 
836  virtual void OnStatusLine(const AString & a_HttpVersion, int a_StatusCode, const AString & a_Rest) override
837  {
838  m_Callbacks->CallTableFnWithSelf("OnStatusLine", a_HttpVersion, a_StatusCode, a_Rest);
839  }
840 
841 
842  virtual void OnHeader(const AString & a_Key, const AString & a_Value) override
843  {
844  m_Callbacks->CallTableFnWithSelf("OnHeader", a_Key, a_Value);
845  m_Headers[a_Key] = a_Value;
846  }
847 
848 
849  virtual void OnHeadersFinished() override
850  {
851  m_Callbacks->CallTableFnWithSelf("OnHeadersFinished", m_Headers);
852  }
853 
854 
855  virtual void OnBodyData(const void * a_Data, size_t a_Size) override
856  {
857  m_Callbacks->CallTableFnWithSelf("OnBodyData", AString(static_cast<const char *>(a_Data), a_Size));
858  }
859 
860 
861  virtual void OnBodyFinished() override
862  {
863  m_Callbacks->CallTableFnWithSelf("OnBodyFinished");
864  }
865 
866 
867  virtual void OnError(const AString & a_ErrorMsg) override
868  {
869  m_Callbacks->CallTableFnWithSelf("OnError", a_ErrorMsg);
870  }
871 
872 
873  virtual void OnRedirecting(const AString & a_NewLocation) override
874  {
875  m_Callbacks->CallTableFnWithSelf("OnRedirecting", a_NewLocation);
876  }
877 
878 
879 protected:
882 
885 };
886 
887 
888 
889 
890 
899 {
900 public:
903  m_Callback(std::move(a_Callback))
904  {
905  }
906 
907 
908  virtual void OnHeader(const AString & a_Key, const AString & a_Value) override
909  {
910  m_Headers[a_Key] = a_Value;
911  }
912 
913 
914  virtual void OnBodyData(const void * a_Data, size_t a_Size) override
915  {
916  m_ResponseBody.append(static_cast<const char *>(a_Data), a_Size);
917  }
918 
919 
920  virtual void OnBodyFinished() override
921  {
923  }
924 
925 
926  virtual void OnError(const AString & a_ErrorMsg) override
927  {
928  m_Callback->Call(cLuaState::Nil, a_ErrorMsg);
929  }
930 
931 
932 protected:
933 
936 
939 
942 };
943 
944 
945 
946 
947 
951 static int tolua_cUrlClient_Request_Common(lua_State * a_LuaState, const AString & a_Method, int a_UrlStackIdx)
952 {
953  // Check params:
954  cLuaState L(a_LuaState);
955  if (!L.CheckParamString(a_UrlStackIdx))
956  {
957  return 0;
958  }
959 
960  // Read params:
961  AString url, requestBody;
962  AStringMap headers, options;
963  cLuaState::cTableRefPtr callbacks;
964  cLuaState::cCallbackPtr onCompleteBodyCallback;
965  if (!L.GetStackValues(a_UrlStackIdx, url))
966  {
967  return L.ApiParamError(fmt::format(FMT_STRING("Cannot read URL parameter at idx {}"), a_UrlStackIdx));
968  }
969  cUrlClient::cCallbacksPtr urlClientCallbacks;
970  if (lua_istable(L, a_UrlStackIdx + 1))
971  {
972  if (!L.GetStackValue(a_UrlStackIdx + 1, callbacks))
973  {
974  return L.ApiParamError(fmt::format(FMT_STRING("Cannot read the CallbacksTable parameter at idx {}"), a_UrlStackIdx + 1));
975  }
976  urlClientCallbacks = std::make_unique<cFullUrlClientCallbacks>(std::move(callbacks));
977  }
978  else if (lua_isfunction(L, a_UrlStackIdx + 1))
979  {
980  if (!L.GetStackValue(a_UrlStackIdx + 1, onCompleteBodyCallback))
981  {
982  return L.ApiParamError(fmt::format(FMT_STRING("Cannot read the CallbackFn parameter at idx {}"), a_UrlStackIdx + 1));
983  }
984  urlClientCallbacks = std::make_unique<cSimpleUrlClientCallbacks>(std::move(onCompleteBodyCallback));
985  }
986  else
987  {
988  L.ApiParamError(fmt::format(
989  FMT_STRING("Invalid Callbacks parameter at {}, expected a table or function, got {}"),
990  a_UrlStackIdx + 1, L.GetTypeText(a_UrlStackIdx + 1)
991  ));
992  }
994  {
995  L.ApiParamError(fmt::format(
996  FMT_STRING("Cannot read the Header, Body or Options parameter at idx {}, {}, {}."),
997  a_UrlStackIdx + 2, a_UrlStackIdx + 3, a_UrlStackIdx + 4
998  ));
999  }
1000 
1001  // Make the request:
1002  auto res = cUrlClient::Request(a_Method, url, std::move(urlClientCallbacks), std::move(headers), std::move(requestBody), std::move(options));
1003  if (!res.first)
1004  {
1005  L.Push(false);
1006  L.Push(res.second);
1007  return 2;
1008  }
1009  L.Push(true);
1010  return 1;
1011 }
1012 
1013 
1014 
1015 
1016 
1018 static int tolua_cUrlClient_Delete(lua_State * a_LuaState)
1019 {
1020  /* Function signatures:
1021  cUrlClient:Delete(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1022  cUrlClient:Delete(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1023  */
1024 
1025  return tolua_cUrlClient_Request_Common(a_LuaState, "DELETE", 2);
1026 }
1027 
1028 
1029 
1030 
1031 
1033 static int tolua_cUrlClient_Get(lua_State * a_LuaState)
1034 {
1035  /* Function signatures:
1036  cUrlClient:Get(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1037  cUrlClient:Get(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1038  */
1039 
1040  return tolua_cUrlClient_Request_Common(a_LuaState, "GET", 2);
1041 }
1042 
1043 
1044 
1045 
1046 
1048 static int tolua_cUrlClient_Post(lua_State * a_LuaState)
1049 {
1050  /* Function signatures:
1051  cUrlClient:Post(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1052  cUrlClient:Post(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1053  */
1054 
1055  return tolua_cUrlClient_Request_Common(a_LuaState, "POST", 2);
1056 }
1057 
1058 
1059 
1060 
1061 
1063 static int tolua_cUrlClient_Put(lua_State * a_LuaState)
1064 {
1065  /* Function signatures:
1066  cUrlClient:Put(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1067  cUrlClient:Put(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1068  */
1069 
1070  return tolua_cUrlClient_Request_Common(a_LuaState, "PUT", 2);
1071 }
1072 
1073 
1074 
1075 
1076 
1078 static int tolua_cUrlClient_Request(lua_State * a_LuaState)
1079 {
1080  /* Function signatures:
1081  cUrlClient:Request(Method, URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1082  cUrlClient:Request(Method, URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
1083  */
1084 
1085  // Check that the Method param is a string:
1086  cLuaState L(a_LuaState);
1087  if (
1088  !L.CheckParamStaticSelf("cUrlClient") ||
1089  !L.CheckParamString(2))
1090  {
1091  return 0;
1092  }
1093 
1094  // Redirect the rest to the common code:
1095  AString method;
1096  if (!L.GetStackValue(2, method))
1097  {
1098  L.ApiParamError("Cannot read the Method parameter");
1099  }
1100  return tolua_cUrlClient_Request_Common(a_LuaState, method, 3);
1101 }
1102 
1103 
1104 
1105 
1106 
1108 // Register the bindings:
1109 
1110 void cManualBindings::BindNetwork(lua_State * tolua_S)
1111 {
1112  // Create the cNetwork API classes:
1113  tolua_usertype(tolua_S, "cNetwork");
1114  tolua_usertype(tolua_S, "cServerHandle");
1115  tolua_usertype(tolua_S, "cTCPLink");
1116  tolua_usertype(tolua_S, "cUDPEndpoint");
1117  tolua_usertype(tolua_S, "cUrlClient");
1118  tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr);
1119  tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle);
1120  tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr);
1121  tolua_cclass(tolua_S, "cUDPEndpoint", "cUDPEndpoint", "", tolua_collect_cUDPEndpoint);
1122  tolua_cclass(tolua_S, "cUrlClient", "cUrlClient", "", nullptr);
1123 
1124  // Fill in the functions (alpha-sorted):
1125  tolua_beginmodule(tolua_S, "cNetwork");
1126  tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect);
1127  tolua_function(tolua_S, "CreateUDPEndpoint", tolua_cNetwork_CreateUDPEndpoint);
1128  tolua_function(tolua_S, "EnumLocalIPAddresses", tolua_cNetwork_EnumLocalIPAddresses);
1129  tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP);
1130  tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname);
1131  tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen);
1132  tolua_endmodule(tolua_S);
1133 
1134  tolua_beginmodule(tolua_S, "cServerHandle");
1135  tolua_function(tolua_S, "Close", tolua_cServerHandle_Close);
1136  tolua_function(tolua_S, "IsListening", tolua_cServerHandle_IsListening);
1137  tolua_endmodule(tolua_S);
1138 
1139  tolua_beginmodule(tolua_S, "cTCPLink");
1140  tolua_function(tolua_S, "Close", tolua_cTCPLink_Close);
1141  tolua_function(tolua_S, "GetLocalIP", tolua_cTCPLink_GetLocalIP);
1142  tolua_function(tolua_S, "GetLocalPort", tolua_cTCPLink_GetLocalPort);
1143  tolua_function(tolua_S, "GetRemoteIP", tolua_cTCPLink_GetRemoteIP);
1144  tolua_function(tolua_S, "GetRemotePort", tolua_cTCPLink_GetRemotePort);
1145  tolua_function(tolua_S, "Send", tolua_cTCPLink_Send);
1146  tolua_function(tolua_S, "Shutdown", tolua_cTCPLink_Shutdown);
1147  tolua_function(tolua_S, "StartTLSClient", tolua_cTCPLink_StartTLSClient);
1148  tolua_function(tolua_S, "StartTLSServer", tolua_cTCPLink_StartTLSServer);
1149  tolua_endmodule(tolua_S);
1150 
1151  tolua_beginmodule(tolua_S, "cUDPEndpoint");
1152  tolua_function(tolua_S, "Close", tolua_cUDPEndpoint_Close);
1153  tolua_function(tolua_S, "EnableBroadcasts", tolua_cUDPEndpoint_EnableBroadcasts);
1154  tolua_function(tolua_S, "GetPort", tolua_cUDPEndpoint_GetPort);
1155  tolua_function(tolua_S, "IsOpen", tolua_cUDPEndpoint_IsOpen);
1156  tolua_function(tolua_S, "Send", tolua_cUDPEndpoint_Send);
1157  tolua_endmodule(tolua_S);
1158 
1159  tolua_beginmodule(tolua_S, "cUrlClient");
1160  tolua_function(tolua_S, "Delete", tolua_cUrlClient_Delete);
1161  tolua_function(tolua_S, "Get", tolua_cUrlClient_Get);
1162  tolua_function(tolua_S, "Post", tolua_cUrlClient_Post);
1163  tolua_function(tolua_S, "Put", tolua_cUrlClient_Put);
1164  tolua_function(tolua_S, "Request", tolua_cUrlClient_Request);
1165  tolua_endmodule(tolua_S);
1166 }
1167 
1168 
1169 
1170 
static int tolua_cTCPLink_Send(lua_State *L)
Binds cLuaTCPLink::Send.
static int tolua_cUDPEndpoint_Send(lua_State *L)
Binds cLuaUDPEndpoint::Send.
static int tolua_cUrlClient_Put(lua_State *a_LuaState)
Implements cUrlClient:Put() using cUrlClient::Request().
static int tolua_cTCPLink_GetRemotePort(lua_State *L)
Binds cLuaTCPLink::GetRemotePort.
static int tolua_cTCPLink_GetRemoteIP(lua_State *L)
Binds cLuaTCPLink::GetRemoteIP.
static int tolua_cTCPLink_Shutdown(lua_State *L)
Binds cLuaTCPLink::Shutdown.
static int tolua_cTCPLink_StartTLSServer(lua_State *L)
Binds cLuaTCPLink::StartTLSServer.
static int tolua_cUDPEndpoint_EnableBroadcasts(lua_State *L)
Binds cLuaUDPEndpoint::EnableBroadcasts.
static int tolua_cUrlClient_Request(lua_State *a_LuaState)
Binds cUrlClient::Request().
static int tolua_cNetwork_HostnameToIP(lua_State *L)
Binds cNetwork::HostnameToIP.
static int tolua_collect_cServerHandle(lua_State *L)
Called when Lua destroys the object instance.
static int tolua_cServerHandle_Close(lua_State *L)
Binds cLuaServerHandle::Close.
static int tolua_cTCPLink_GetLocalIP(lua_State *L)
Binds cLuaTCPLink::GetLocalIP.
static int tolua_cUDPEndpoint_Close(lua_State *L)
Binds cLuaUDPEndpoint::Close.
static int tolua_cTCPLink_Close(lua_State *L)
Binds cLuaTCPLink::Close.
static int tolua_cNetwork_Listen(lua_State *L)
Binds cNetwork::Listen.
static int tolua_cUrlClient_Get(lua_State *a_LuaState)
Implements cUrlClient:Get() using cUrlClient::Request().
static int tolua_cTCPLink_StartTLSClient(lua_State *L)
Binds cLuaTCPLink::StartTLSClient.
static int tolua_cNetwork_Connect(lua_State *L)
Binds cNetwork::Connect.
static int tolua_cUrlClient_Request_Common(lua_State *a_LuaState, const AString &a_Method, int a_UrlStackIdx)
Common code shared among the cUrlClient request methods.
static int tolua_collect_cUDPEndpoint(lua_State *L)
Called when Lua destroys the object instance.
static int tolua_cUDPEndpoint_GetPort(lua_State *L)
Binds cLuaUDPEndpoint::GetPort.
static int tolua_cTCPLink_GetLocalPort(lua_State *L)
Binds cLuaTCPLink::GetLocalPort.
static int tolua_cServerHandle_IsListening(lua_State *L)
Binds cLuaServerHandle::IsListening.
static int tolua_cUDPEndpoint_IsOpen(lua_State *L)
Binds cLuaUDPEndpoint::IsOpen.
static int tolua_cNetwork_EnumLocalIPAddresses(lua_State *L)
Binds cNetwork::EnumLocalIPAddresses.
static int tolua_cUrlClient_Post(lua_State *a_LuaState)
Implements cUrlClient:Post() using cUrlClient::Request().
static int tolua_cUrlClient_Delete(lua_State *a_LuaState)
Implements cUrlClient:Get() using cUrlClient::Request().
static int tolua_cNetwork_CreateUDPEndpoint(lua_State *L)
Binds cNetwork::CreateUDPEndpoint.
static int tolua_cNetwork_IPToHostname(lua_State *L)
Binds cNetwork::IPToHostname.
#define ASSERT(x)
Definition: Globals.h:276
unsigned short UInt16
Definition: Globals.h:158
std::string AString
Definition: StringUtils.h:11
std::map< AString, AString > AStringMap
A string dictionary, used for key-value pairs.
Definition: StringUtils.h:16
Definition: FastNBT.h:132
Encapsulates a Lua state and provides some syntactic sugar for common operations.
Definition: LuaState.h:56
void Push(Arg1 &&a_Arg1, Arg2 &&a_Arg2, Args &&... a_Args)
Pushes multiple arguments onto the Lua stack.
Definition: LuaState.h:604
std::unique_ptr< cCallback > cCallbackPtr
Definition: LuaState.h:326
bool CheckParamEnd(int a_Param)
Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters)
Definition: LuaState.cpp:1998
bool CheckParamSelf(const char *a_SelfClassName)
Returns true if the first parameter is an instance of the expected class name.
Definition: LuaState.cpp:2018
static const cRet Return
Definition: LuaState.h:445
std::unique_ptr< cTableRef > cTableRefPtr
Definition: LuaState.h:419
bool CheckParamString(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are strings; also logs warning if not.
Definition: LuaState.cpp:1829
bool CheckParamNumber(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are numbers; also logs warning if not.
Definition: LuaState.cpp:1763
AString GetTypeText(int a_StackPos)
Returns the type of the item on the specified position in the stack.
Definition: LuaState.cpp:2185
static const cNil Nil
Definition: LuaState.h:452
bool CheckParamTable(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are tables; also logs warning if not.
Definition: LuaState.cpp:1727
bool CheckParamStaticSelf(const char *a_SelfClassName)
Returns true if the first parameter is the expected class (static).
Definition: LuaState.cpp:2043
bool GetStackValue(int a_StackPos, AString &a_Value)
Definition: LuaState.cpp:1119
int ApiParamError(std::string_view a_Msg)
Prints the message, prefixed with the current function name, then logs the stack contents and raises ...
Definition: LuaState.cpp:2161
bool GetStackValues(int a_StartStackPos, Arg1 &&a_Arg1, Args &&... args)
Retrieves a list of values from the Lua stack, starting at the specified index.
Definition: LuaState.h:766
Represents a parameter that is optional - calling a GetStackValue() with this object will not fail if...
Definition: LuaState.h:427
Used when the cUrlClient Lua request wants all the callbacks.
virtual void OnHeadersFinished() override
Called when the HTTP headers have been fully parsed, unless the response is an allowed redirect.
virtual void OnBodyFinished() override
Called after the response body has been fully reported by OnBody() calls, unless the response is an a...
cFullUrlClientCallbacks(cLuaState::cTableRefPtr &&a_Callbacks)
Creates a new instance bound to the specified table of callbacks.
AStringMap m_Headers
Accumulator for all the headers to be reported in the OnHeadersFinished() callback.
virtual void OnRedirecting(const AString &a_NewLocation) override
Called when a redirect is to be followed.
virtual bool OnCertificateReceived() override
Called for TLS connections, when the server certificate is received.
virtual void OnConnected(cTCPLink &a_Link) override
Called when the TCP connection is established.
virtual void OnHeader(const AString &a_Key, const AString &a_Value) override
Called when a single HTTP header is received and parsed, unless the response is an allowed redirect C...
virtual void OnRequestSent() override
Called after the entire request has been sent to the remote peer.
virtual void OnStatusLine(const AString &a_HttpVersion, int a_StatusCode, const AString &a_Rest) override
Called after the first line of the response is parsed, unless the response is an allowed redirect.
cLuaState::cTableRefPtr m_Callbacks
The Lua table containing the callbacks.
virtual void OnBodyData(const void *a_Data, size_t a_Size) override
Called when the next fragment of the response body is received, unless the response is an allowed red...
virtual void OnError(const AString &a_ErrorMsg) override
Called when an asynchronous error is encountered.
virtual void OnTlsHandshakeCompleted() override
Called for TLS connections, when the TLS handshake has been completed.
Used when the cUrlClient Lua request has just a single callback.
virtual void OnBodyFinished() override
Called after the response body has been fully reported by OnBody() calls, unless the response is an a...
virtual void OnHeader(const AString &a_Key, const AString &a_Value) override
Called when a single HTTP header is received and parsed, unless the response is an allowed redirect C...
cSimpleUrlClientCallbacks(cLuaState::cCallbackPtr &&a_Callback)
Creates a new instance that uses the specified callback to report when request finishes.
AString m_ResponseBody
The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once...
AStringMap m_Headers
Accumulator for all the headers to be reported in the combined callback.
virtual void OnError(const AString &a_ErrorMsg) override
Called when an asynchronous error is encountered.
cLuaState::cCallbackPtr m_Callback
The callback to call when the request finishes.
virtual void OnBodyData(const void *a_Data, size_t a_Size) override
Called when the next fragment of the response body is received, unless the response is an allowed red...
std::shared_ptr< cCallbacks > cCallbacksPtr
Definition: UrlClient.h:90
static std::pair< bool, AString > Request(const AString &a_Method, const AString &a_URL, cCallbacksPtr &&a_Callbacks, AStringMap &&a_Headers, const AString &a_Body, const AStringMap &a_Options)
Makes a network request to the specified URL, using the specified method (if applicable).
Definition: UrlClient.cpp:675
Callbacks that are used for progress and result reporting.
Definition: UrlClient.h:39
Interface that provides the methods available on a single TCP connection.
Definition: Network.h:42
virtual UInt16 GetRemotePort(void) const =0
Returns the port used by the remote endpoint of the connection.
virtual AString GetRemoteIP(void) const =0
Returns the IP address of the remote endpoint of the 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.
static AStringVector EnumLocalIPAddresses(void)
Returns all local IP addresses for network interfaces currently available.
static cServerHandlePtr Listen(UInt16 a_Port, cListenCallbacksPtr a_ListenCallbacks)
Opens up the specified port for incoming connections.
static bool HostnameToIP(const AString &a_Hostname, cResolveNameCallbacksPtr a_Callbacks)
Queues a DNS query to resolve the specified hostname to IP address.
static bool IPToHostName(const AString &a_IP, cResolveNameCallbacksPtr a_Callbacks)
Queues a DNS query to resolve the specified IP address to a hostname.
Definition: IPLookup.cpp:91