demonstrate how to open a socket
[fg:hoorays-flightgear.git] / src / Scripting / NasalFGProtocol.cxx
1 // Expose FGProtocol module to Nasal to enable I/O protocols to be implemented in Nasal space, e.g.
2 // to support REST/AJAX, JSON or HTTP WebSockets
3 //
4 // Copyright (C) 2013  The FlightGear community
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "NasalFGProtocol.hxx"
25 #include <Main/globals.hxx>
26 #include <Main/util.hxx>
27 #include <Main/fg_io.hxx>
28
29 // supported SGIOChannels
30 #include <simgear/io/iochannel.hxx>
31 #include <simgear/io/sg_file.hxx>
32 #include <simgear/io/sg_serial.hxx>
33 #include <simgear/io/sg_socket.hxx>
34 #include <simgear/io/sg_socket_udp.hxx>
35
36 #include <simgear/nasal/cppbind/from_nasal.hxx>
37 #include <simgear/nasal/cppbind/to_nasal.hxx>
38 #include <simgear/nasal/cppbind/NasalHash.hxx>
39 #include <simgear/nasal/cppbind/Ghost.hxx>
40
41
42
43 class NasalProtocolWrapper;
44
45 typedef boost::shared_ptr<NasalProtocolWrapper> NasalProtocolWrapper_ptr;
46 typedef nasal::Ghost< NasalProtocolWrapper_ptr > NasalProtocol;
47
48 class NasalProtocolWrapper : public FGProtocol {
49 public:
50  NasalProtocolWrapper(const nasal::CallContext& ctx);
51  void register_handler();
52  bool open();
53  bool process();
54  bool close();
55  bool gen_message();
56  bool parse_message();
57  void set_direction();
58  
59 protected:
60 private:
61 };
62
63 NasalProtocolWrapper::NasalProtocolWrapper(const nasal::CallContext& ctx) {
64    //TODO: see parse_port_config in Main/fg_io.cxx
65   std::string medium = ctx.requireArg<std::string>(0);  
66   std::string direction = ctx.requireArg<std::string>(1);  
67   std::string rate_hz = ctx.requireArg<std::string>(2);  
68
69  FGProtocol::set_direction( direction ); 
70
71  if(medium=="socket") {
72         std::string host = ctx.requireArg<std::string>(3);
73         std::string port = ctx.requireArg<std::string>(4); 
74         std::string style = ctx.requireArg<std::string>(5); 
75         // http://docs.freeflightsim.org/simgear/classSGSocket.html
76         set_io_channel( new SGSocket( host, port, style ) );
77  }
78  else 
79   SG_LOG(SG_IO, SG_ALERT, "NasalProtocolWrapper: Unsupported medium: "<< medium << std::endl);
80 }
81
82
83
84 void 
85 NasalProtocolWrapper::register_handler() {
86   static_cast<FGIO*> (globals->get_subsystem( "io" )) ->add_channel( this );
87 }
88
89 bool
90 NasalProtocolWrapper::open() {
91 SG_LOG(SG_GENERAL, SG_ALERT, "::open" << std::endl);
92 FGProtocol::open();
93 return true;
94 }
95
96 bool
97 NasalProtocolWrapper::process() {
98 SG_LOG(SG_GENERAL, SG_ALERT, "::process" << std::endl);
99 FGProtocol::process();
100 return true;
101 }
102
103 bool
104 NasalProtocolWrapper::close() {
105 SG_LOG(SG_GENERAL, SG_ALERT, "::close" << std::endl);
106 FGProtocol::close();
107 return true;
108 }
109
110 bool
111 NasalProtocolWrapper::gen_message() {
112 SG_LOG(SG_GENERAL, SG_ALERT, "::gen_message" << std::endl);
113 return true;
114 }
115
116 bool
117 NasalProtocolWrapper::parse_message() {
118 SG_LOG(SG_GENERAL, SG_ALERT, "::parse_message" << std::endl);
119 return true;
120 }
121
122 void
123 NasalProtocolWrapper::set_direction() {
124 SG_LOG(SG_GENERAL, SG_ALERT, "::set_direction" << std::endl);
125
126 }
127
128
129
130 naRef to_nasal_helper(naContext c, NasalProtocolWrapper *obj)
131   { 
132     NasalProtocolWrapper_ptr ptr(obj); 
133     return NasalProtocol::create(c, ptr ); 
134   }
135  
136
137 NasalProtocolWrapper*
138 from_nasal_helper(naContext c, naRef ref, const NasalProtocolWrapper*)
139   { 
140       return (NasalProtocolWrapper*) naGhost_ptr(ref);
141   }
142
143 static naRef f_new_protocol(const nasal::CallContext& ctx)
144 {
145  NasalProtocolWrapper* proto = NULL;
146  try {
147    proto = new NasalProtocolWrapper(ctx);
148   }
149   catch(...) {
150    return naNil();
151   }
152
153   return ctx.to_nasal( proto );
154 }
155
156 //------------------------------------------------------------------------------
157 naRef initNasalFGProtocol(naRef globals, naContext c)
158 {
159   NasalProtocol::init("io.protocol")
160 // This is where you want to expose various methods from FGProtocol/NetChat/NetChannel
161         .method("register", &NasalProtocolWrapper::register_handler) 
162         .method("open", &NasalProtocolWrapper::open) 
163         .method("close", &NasalProtocolWrapper::close) 
164         .method("gen_message", &NasalProtocolWrapper::gen_message) 
165         .method("parse_message", &NasalProtocolWrapper::parse_message) 
166         .method("set_direction", &NasalProtocolWrapper::set_direction);
167
168   nasal::Hash globals_module(globals, c);
169   nasal::Hash protocol = globals_module.createHash("protocol");
170   protocol.set("new", &f_new_protocol); 
171
172   return naNil();
173 }