aboutsummaryrefslogtreecommitdiffstats
path: root/reference
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2018-03-01 10:28:17 -0300
committerVitor Sousa <vitorsousasilva@gmail.com>2018-03-01 10:28:17 -0300
commit566b5c3ee732b1f76d873d0544638fc53ae24b73 (patch)
tree487be60dc2d00af0432a7220eafdb90e7b94623d /reference
parenteo_mono: add eo-intro tutorial for C# (diff)
downloadexamples-566b5c3ee732b1f76d873d0544638fc53ae24b73.tar.gz
net_mono: add net reference examples to the C# binding
Diffstat (limited to 'reference')
-rw-r--r--reference/csharp/net/meson.build10
-rw-r--r--reference/csharp/net/src/meson.build22
-rw-r--r--reference/csharp/net/src/net_io.cs269
-rw-r--r--reference/csharp/net/src/net_io_buffered.cs181
-rw-r--r--reference/csharp/net/src/net_session.cs135
5 files changed, 617 insertions, 0 deletions
diff --git a/reference/csharp/net/meson.build b/reference/csharp/net/meson.build
new file mode 100644
index 00000000..18a81719
--- /dev/null
+++ b/reference/csharp/net/meson.build
@@ -0,0 +1,10 @@
+project(
+ 'efl-reference-net', 'c',
+ version : '0.0.1',
+ meson_version : '>= 0.38.0')
+
+efl_mono = dependency('efl-mono', version : '>=1.20.99')
+efl_mono_libs = efl_mono.get_pkgconfig_variable('mono_libs')
+
+subdir('src')
+
diff --git a/reference/csharp/net/src/meson.build b/reference/csharp/net/src/meson.build
new file mode 100644
index 00000000..9897ac68
--- /dev/null
+++ b/reference/csharp/net/src/meson.build
@@ -0,0 +1,22 @@
+deps = [efl_mono]
+
+executable('efl_reference_net_io',
+ files(['net_io.cs']),
+ dependencies : deps,
+ cs_args : efl_mono_libs,
+ install : true
+)
+
+executable('efl_reference_net_io_buffered',
+ files(['net_io_buffered.cs']),
+ dependencies : deps,
+ cs_args : efl_mono_libs,
+ install : true
+)
+
+executable('efl_reference_net_session',
+ files(['net_session.cs']),
+ dependencies : deps,
+ cs_args : efl_mono_libs,
+ install : true
+)
diff --git a/reference/csharp/net/src/net_io.cs b/reference/csharp/net/src/net_io.cs
new file mode 100644
index 00000000..f7978672
--- /dev/null
+++ b/reference/csharp/net/src/net_io.cs
@@ -0,0 +1,269 @@
+/*
+ * Efl.Net input/output examples.
+ *
+ * This example builds on the core_io example by connecting to a remote server
+ * using a dialer and a command queue. The response is printed to stdout.
+ */
+
+using System;
+
+public class ExampleRunner
+{
+ private eina.List<efl.io.Copier> waiting = null;
+ private eina.List<string> commands = null;
+ private eina.Slice delimiter;
+ private efl.net.dialer.Tcp dialer = null;
+ private efl.io.Copier sender = null;
+ private efl.io.Copier receiver = null;
+
+ public void Run()
+ {
+ efl.ui.Config.Run();
+ }
+
+ // call this method to cleanly shut down our example
+ public void Quit()
+ {
+ if (waiting != null)
+ {
+ Console.Error.WriteLine("ERROR: {0} operations were waiting!", waiting.Length);
+ waiting.Dispose();
+ waiting = null;
+ }
+
+ if (receiver != null)
+ {
+ receiver.Close();
+ receiver.GetDestination().Dispose();
+ receiver.Dispose();
+ receiver = null;
+ }
+
+ if (sender)
+ {
+ sender.Close();
+ sender.GetSource().Dispose();
+ source.Dispose();
+ }
+
+ if (dialer)
+ dialer.Dispose();
+
+ // efl_exit(retval); // TODO missing
+ efl.ui.Config.Exit();
+ }
+
+ // iterate through the commands to send through the dialler
+ public void CommandNext()
+ {
+ efl.io.Reader send_queue = sender.GetSource();
+ if (commands != null)
+ {
+ send_queue.EosMark();
+ return;
+ }
+
+ string cmd = commands[0];
+ // commands.RemoveAt(0); // TODO missing
+
+ eina.Slice slice;
+ // slice = (Eina_Slice)EINA_SLICE_STR(cmd); // TODO missing
+ send_queue.Write(slice, null);
+ // Console.WriteLine("INFO: sent '{0}'", EINA_SLICE_STR_PRINT(slice)); // TODO missing
+
+ // don't use delimiter directly, 'Len' may be changed!
+ slice = delimiter;
+ send_queue.Write(slice, null);
+ }
+
+ void ReceiverData(efl.io.Queue sender, EventArgs e)
+ {
+ eina.Slice slice = sender.GetSlice();
+
+ // Can be caused when we issue efl.io.Queue.Clear()
+ if (slice.Len == 0) return;
+
+ // If the server didn't send us the line terminator and closed the
+ // connection (ie: efl_io_reader_eos_get() == true) or if the buffer
+ // limit was reached then we may have a line without a trailing delimiter.
+
+ // if (slice.EndsWith(delimiter)) // TODO missing
+ // slice.Len -= delimiter.Len;
+
+ // Console.WriteLine("INFO: received '{0}'", EINA_SLICE_STR_PRINT(slice)); // TODO missing
+
+ sender.Clear();
+ CommandNext();
+ }
+
+ void DialerConnected(efl.net.dialer.Tcp sender, EventArgs e)
+ {
+ Console.WriteLine("INFO: connected to {0} ({1})", sender.GetAddressDial(), sender.GetAddressRemote());
+
+ CommandNext();
+ }
+
+ void CopierDone(efl.io.Copier sender, EventArgs e)
+ {
+ Console.WriteLine("INFO: {0} done", sender.GetName());
+
+ // waiting.Remove(sender); // TODO missing
+ if (waiting.Empty())
+ Quit(EXIT_SUCCESS);
+ }
+
+ void CopierError(efl.io.Copier sender, eina.Error perr)
+ {
+ Console.Error.WriteLine(stderr, "INFO: {0} error: #{1} '{2}'", sender.GetName(), perr, perr.Message);
+
+ Quit(EXIT_FAILURE);
+ }
+
+ private static void SetCopierCbs(efl.io.Copier copier)
+ {
+ copier.DONE += CopierDone;
+ copier.ERROR += CopierError;
+ }
+
+
+ public ExampleRunner()
+ {
+ string address = "example.com:80";
+ ulong buffer_limit = 128;
+ efl.io.Queue send_queue, receive_queue;
+
+ commands = new eina.List<string>();
+ commands.Append("HEAD / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
+ // delimiter = (Eina_Slice)EINA_SLICE_STR("\r\n"); // TODO missing
+
+ // Without a send_queue we'd have to manually implement an
+ // efl.io.Reader object that would provide partial data when
+ // efl.io.Reader.read() is called by efl.io.Copier. This is
+ // cumbersome... we just want to write a full command and have the
+ // queue to handle that for us.
+ //
+ // Our example's usage is to write each command at once followed by
+ // the line delimiter, then wait for a reply from the server, then
+ // write another.
+
+ try
+ {
+ send_queue = new efl.io.QueueConcrete(null, (efl.io.Queue equeue) => {
+ equeue.SetName("send_queue");
+ equeue.SetLimit(buffer_limit);
+ });
+ }
+ catch
+ {
+ Console.Error.WriteLine("ERROR: could not create efl.io.Queue (send)");
+ Quit(EXIT_FAILURE);
+ throw;
+ }
+
+ // Without a receive_queue we'd have to manually implement an
+ // efl.io.Writer object that would handle write of partial data
+ // with efl.io.Writer.write() is called by efl.io.Copier.
+ //
+ // For output we could have another solution as well: use null
+ // destination and handle "line" or "data" events manually,
+ // stealing the buffer so it doesn't grow.
+ //
+ // Our example's usage is to peek its data with GetSlice() then
+ // Clear().
+ try
+ {
+ receive_queue = new efl.io.QueueConcrete(null, (efl.io.Queue equeue) => {
+ equeue.SetName("receive_queue");
+ equeue.SetLimit(buffer_limit);
+ });
+ receive_queue.SLICE_CHANGED += ReceiverData;
+ }
+ catch
+ {
+ Console.Error.WriteLine("ERROR: could not create efl.io.Queue (receive)");
+ Quit(EXIT_FAILURE);
+ throw;
+ }
+
+ // some objects such as the Efl.Io.Copier and Efl.Net.Dialer.Tcp
+ // depend on main loop, thus their parent must be a loop
+ // provider. We use the loop passed to our main method.
+ // efl.Loop loop = ev->object; // TODO missing
+
+ // The TCP client to use to send/receive network data
+ try
+ {
+ dialer = new efl.net.dialer.TcpConcrete(loop, (efl.net.dialer.Tcp edialer) => {
+ edialer.SetName("dialer");
+ });
+ dialer.CONNECTED += DialerConnected;
+ }
+ catch
+ {
+ Console.Error.WriteLine("ERROR: could not create efl.net.dialer.Tcp");
+ Quit(EXIT_FAILURE);
+ throw;
+ }
+
+ // sender: send_queue->network
+ try
+ {
+ sender = new efl.io.CopierConcrete(loop, (efl.io.Copier esender) => {
+ esender.SetName("sender");
+ esender.SetLineDelimiter(delimiter);
+ esender.SetSource(send_queue);
+ esender.SetDestination(dialer);
+ });
+ SetCopierCbs(sender);
+ }
+ catch
+ {
+ Console.Error.WriteLine("ERROR: could not create efl.io.Copier (sender)");
+ Quit(EXIT_FAILURE);
+ throw;
+ }
+
+ // receiver: network->receive_queue
+ try
+ {
+ receiver = new efl.io.CopierConcrete(loop, (efl.io.Copier ereceiver) => {
+ ereceiver.SetName("receiver");
+ ereceiver.SetLineDelimiter(delimiter);
+ ereceiver.SetSource(dialer);
+ ereceiver.SetDestination(send_queue);
+ });
+ SetCopierCbs(receiver);
+ }
+ catch
+ {
+ Console.Error.WriteLine("ERROR: could not create Efl_Io_Copier (receiver)");
+ Quit(EXIT_FAILURE);
+ throw;
+ }
+
+ eina.Error err = dialer.Dial(address);
+ if (err != eina.Error.NO_ERROR)
+ {
+ var msg = $"ERROR: could not dial {address}: {err.Message}";
+ Console.Error.WriteLine(msg);
+ Quit(EXIT_FAILURE);
+ throw new SEHException(msg);
+ }
+
+ waiting.Append(sender);
+ waiting.Append(receiver);
+ }
+}
+
+public static class Example
+{
+ public static void Main()
+ {
+ efl.All.Init(efl.Components.Basic);
+
+ var exr = new ExampleRunner();
+ exr.Run();
+
+ efl.All.Shutdown();
+ }
+}
diff --git a/reference/csharp/net/src/net_io_buffered.cs b/reference/csharp/net/src/net_io_buffered.cs
new file mode 100644
index 00000000..3a159e75
--- /dev/null
+++ b/reference/csharp/net/src/net_io_buffered.cs
@@ -0,0 +1,181 @@
+/*
+ * Efl.Net buffered input/output examples.
+ *
+ * This example builds on the net_io example by using a buffered_stream to
+ * simplify the logic. This helpfully provides the input and output queues
+ * and a copier internally. They can be accessed from the buffered stream
+ * if required but as demonstrated here that is likely not necessary.
+ */
+
+using System;
+
+public class ExampleRunner
+{
+ private eina.List<string> commands = null;
+ private eina.Slice delimiter;
+ private efl.net.dialer.Tcp dialer = null;
+ private efl.io.buffered.Stream stream = null;
+
+ public void Run()
+ {
+ efl.ui.Config.Run();
+ }
+
+ public void Quit(int retval)
+ {
+ if (stream != null)
+ {
+ stream.Close();
+ stream.Dispose();
+ stream = null;
+ }
+
+ if (dialer != null)
+ {
+ dialer.Dispose();
+ dialer = null;
+ }
+
+ // efl_exit(retval); TODO missing
+ efl.ui.Config.Exit();
+ }
+
+ public void CommandNext()
+ {
+ if (commands.Empty())
+ {
+ stream.EosMark();
+ return;
+ }
+
+ string cmd = commands[0];
+ // commands.RemoveAt(0); // TODO missing
+
+ // eina.Slice slice = (Eina_Slice)EINA_SLICE_STR(cmd); // TODO missing
+ stream.Write(slice, null);
+ // Console.Error.WriteLine("INFO: sent '{0}'", EINA_SLICE_STR_PRINT(slice)); // TODO missing
+
+ // don't use delimiter directly, 'Len' may be changed!
+ slice = delimiter;
+ stream.Write(slice, null);
+ }
+
+ void StreamLine(efl.io.buffered.Stream sender, EventArgs e)
+ {
+ eina.Slice slice = sender.GetSlice();
+
+ // Can be caused when we issue efl.io.buffered.Stream.Clear()
+ if (slice.Len == 0) return;
+
+ // If the server didn't send us the line terminator and closed the
+ // connection (ie: efl_io_reader_eos_get() == true) or if the buffer
+ // limit was reached then we may have a line without a trailing delimiter.
+ // if (slice.EndsWith(delimiter)) // TODO missing
+ // slice.Len -= delimiter.Len;
+
+ // Console.WriteLine("INFO: received '{0}'", EINA_SLICE_STR_PRINT(slice)); // TODO missing
+
+ sender.Clear();
+ CommandNext();
+ }
+
+ void DialerConnected(efl.net.dialer.Tcp sender, EventArgs e)
+ {
+ Console.WriteLine("INFO: connected to {0} ({1})", sender.GetAddressDial(), sender.GetAddressRemote());
+
+ CommandNext();
+ }
+
+ void StreamDone(efl.io.buffered.Stream sender, EventArgs e)
+ {
+ Console.WriteLine("INFO: {0} done", sender.GetName());
+
+ Quit(EXIT_SUCCESS);
+ }
+
+ void StreamError(efl.io.buffered.Stream sender, eina.Error err)
+ {
+ Console.Error.WriteLine("INFO: {0} error: #{1} '{2}'", sender;GetName(), err, err.Message);
+
+ Quit(EXIT_FAILURE);
+ }
+
+ private static void SetStreamCbs(efl.io.buffered.Stream s)
+ {
+ s.LINE += StreamLine;
+ s.EOS += StreamDone;
+ s.ERROR += StreamError;
+ }
+
+ public ExampleRunner()
+ {
+ string address = "example.com:80";
+ ulong bufferLimit = 128;
+
+ commands = new eina.List<string>();
+ commands.Append("HEAD / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
+ // delimiter = (Eina_Slice)EINA_SLICE_STR("\r\n"); // TODO missing
+
+ // some objects such as the Efl.Io.Copier and Efl.Net.Dialer.Tcp
+ // depend on main loop, thus their parent must be a loop
+ // provider. We use the loop passed to our main method.
+ // efl.Loop loop = ev->object; // TODO missing
+
+ // The TCP client to use to send/receive network data
+ try
+ {
+ dialer = new efl.net.dialer.TcpConcrete(loop, (efl.net.dialer.Tcp edialer) => {
+ edialer.SetName("dialer");
+ });
+ dialer.CONNECTED += DialerConnected;
+ }
+ catch
+ {
+ Console.Error.WriteLine("ERROR: could not create efl.net.dialer.Tcp");
+ Quit(EXIT_FAILURE);
+ throw;
+ }
+
+
+ // Without the buffered stream we'd have to create two Efl.Io.Queue
+ // ourselves, as well as two Efl.Io.Copier to link them with the
+ // dialer.
+ //
+ // Our example's usage is to write each command at once followed by
+ // the line delimiter, then wait for a reply from the server, then
+ // write another.
+ //
+ // On incoming data we peek at it with GetSlice() and then Clear().
+
+ stream = new efl.io.buffered.StreamConcrete(loop, (efl.io.buffered.Stream estream) => {
+ estream.SetName("stream");
+ estream.SetInnerIo(dialer);
+ estream.SetDelimiter(delimiter);
+ estream.SetMaxQueueSizeInput(bufferLimit);
+ estream.SetMaxQueueSizeOutput(bufferLimit);
+ });
+ SetStreamCbs(stream);
+
+ eina.Error err = dialer.Dial(address);
+ if (err != eina.Error.NO_ERROR)
+ {
+ var msg = $"ERROR: could not dial {address}: {err.Message}";
+ Console.Error.WriteLine(msg);
+ Quit(EXIT_FAILURE);
+ throw new SEHException(msg);
+ }
+ }
+}
+
+public class Example
+{
+ public static void Main()
+ {
+ efl.All.Init(efl.Components.Basic);
+
+ var exr = new ExampleRunner();
+ exr.Run();
+
+ efl.All.Shutdown();
+ }
+}
diff --git a/reference/csharp/net/src/net_session.cs b/reference/csharp/net/src/net_session.cs
new file mode 100644
index 00000000..2c703970
--- /dev/null
+++ b/reference/csharp/net/src/net_session.cs
@@ -0,0 +1,135 @@
+/*
+ * Efl.Net session/connectivity examples.
+ *
+ * NOTE: This example currently requires the Connman backend to be running.
+ *
+ * This example uses the Efl.Net.Session APIs to get connectivity information
+ * about the current networking setup. It then sets up a callback for network
+ * changes and will print the details on any change.
+ */
+
+using System;
+
+public class Example
+{
+ // Convert a session state to a string for printing.
+ public static string StateName(efl.net.session.State state)
+ {
+ switch (state)
+ {
+ case efl.net.session.State.Offline:
+ return "offline";
+ case efl.net.session.State.Local:
+ return "local";
+ case efl.net.session.State.Online:
+ return "online";
+ default:
+ return "???";
+ }
+ }
+
+ private static readonly Dictionary<efl.net.session.Technology, string> names =
+ new Dictionary<efl.net.session.Technology, string> {
+ { efl.net.session.Technology.Unknown, "unknown" },
+ { efl.net.session.Technology.Ethernet, "ethernet" },
+ { efl.net.session.Technology.Wifi, "wifi" },
+ { efl.net.session.Technology.Bluetooth, "bluetooth" },
+ { efl.net.session.Technology.Cellular, "cellular" },
+ { efl.net.session.Technology.Vpn, "vpn" },
+ { efl.net.session.Technology.Gadget, "gadget" }
+ };
+
+ // Convert a session technology to a string for printing.
+ public static string TechnologyName(efl.net.session.Technology tech)
+ {
+ string name;
+ if (!names.TryGetValue(tech, out name))
+ return "???";
+ return name;
+ }
+
+ // Tthe callback that indicates some connectivity changed within the session.
+ // Print information about the session to the console.
+ static void SessionChanged(efl.net.Session session, EventArgs e)
+ {
+ Console.WriteLine("Session changed:");
+ Console.WriteLine(" name: '{0}'", session.GetName());
+ Console.WriteLine(" state: {0}", StateName(session.GetState()));
+ Console.WriteLine(" technology: {0}", TechnologyName(session.GetTechnology()));
+ Console.WriteLine(" interface: '{0}'", session.GetInterface());
+
+ // print out additional information if we have an IPv4 session
+ string ip, netmask, gateway;
+ session.GetIpv4(out ip, out netmask, out gateway);
+ if (ip != null)
+ {
+ Console.WriteLine($" IPv4: {ip}, gateway={gateway}, netmask={netmask}");
+ }
+
+ // print out additional information if we have an IPv6 session
+ byte prefix;
+ session.GetIpv6(out ip, out prefix, out netmask, out gateway);
+ if (ip != null)
+ {
+ Console.WriteLine($" IPv6: {ip}/{prefix}, gateway={gateway}, netmask={netmask}");
+ }
+ }
+
+ // Quit the app after a timer tick.
+ static void QuitCb(object sender, EventArgs e)
+ {
+ // efl_exit(0); // TODO missing
+ efl.ui.Config.Exit();
+ }
+
+ public static void Main()
+ {
+ bool doConnect = true;
+ bool requireOnline = false;
+
+ efl.All.Init(efl.Components.Basic);
+
+ // efl.Loop loop = ev->object; // TODO missing
+
+ // create a session that watches specifically for ethernet, wifi and bluetooth
+ int technologies = efl.net.session.Technology.Ethernet |
+ efl.net.session.Technology.Wifi | efl.net.session.Technology.Bluetooth;
+
+ try
+ {
+ efl.net.Session session = new efl.net.SessionConcrete(loop, (efl.net.Session esession) => {
+ esession.SetName("Example Session");
+ // register the change callback for network state
+ esession.CHANGED += SessionChanged;
+ });
+ }
+ catch
+ {
+ eina.Log.Error("Could not create Efl.Net.Session object.\n");
+ // efl_exit(EXIT_FAILURE); // TODO missing
+ efl.ui.Config.Exit();
+ throw;
+ }
+
+ if (doConnect)
+ {
+ Console.WriteLine("Requesting a {0} connection.", requireOnline ? "online" : "local");
+ session.Connect(requireOnline, technologies);
+ }
+
+ Console.WriteLine("The session will remain active while this application runs.");
+ Console.WriteLine("Use ^C (Control + C) to close it");
+
+ // Wait for 10 seconds before exiting this example
+ new efl.loop.TimerConcrete(loop, (efl.loop.Timer etimer) => {
+ etimer.SetInterval(10.0);
+ etimer.TICK += QuitCb;
+ });
+
+ // start the main loop
+ efl.ui.Config.Run();
+
+ efl.All.Shutdown();
+ }
+}
+