namespace OpenVPNSocketGUI
import System
import System.Collections
import System.Drawing
import System.Windows.Forms
import System.Net
import System.Net.Sockets
interface NetworkStreamLineConsumer:
def NetworkStreamLineConsume(s as string)
class NetworkStreamLineWatcher:
static final BUFFER_SIZE = 1024; // TODO: turn this down for corner-case testing!
_stream as NetworkStream
_timer as System.Timers.Timer
_buffer as (byte) = array(byte, BUFFER_SIZE)
_partial_string as string
_consumers as List = []
def constructor(stream as NetworkStream):
self._stream = stream
self._timer = System.Timers.Timer()
self._timer.Interval = 200
self._timer.Elapsed += {self._tick()}
self._timer.Enabled = true
self._partial_string = null
def AddConsumer(consumer as NetworkStreamLineConsumer):
self._consumers.Add(consumer)
def Start():
self._timer.Start()
def Stop():
self._timer.Stop()
private def _inform_consumers(s as string):
for consumer as NetworkStreamLineConsumer in self._consumers:
consumer.NetworkStreamLineConsume(s)
private def _tick():
while self._stream.DataAvailable:
read_length = self._stream.Read(self._buffer, 0, BUFFER_SIZE)
read_string = System.Text.ASCIIEncoding.ASCII.GetString(self._buffer[:read_length])
substrings = read_string.Split(char('\n'))
if substrings.Length == 1:
// only a partial line
if self._partial_string == null:
self._partial_string = substrings[0]
else:
self._partial_string += substrings[0]
return
elif substrings.Length > 1:
// first line first
if self._partial_string == null:
self._inform_consumers(substrings[0])
else:
self._inform_consumers(self._partial_string + substrings[0])
self._partial_string = null
for s in substrings[1:-1]:
self._inform_consumers(s)
if substrings[-1].Length != 0:
self._partial_string = substrings[-1]
interface VpnStateWatcher:
def VpnStateChange(new_text as string)
def VpnLogLine(new_text as string)
class VpnState(NetworkStreamLineConsumer):
[property(State)]
_state_text as string
_watchers as List
_tcpclient as TcpClient
_tcpclient_stream as NetworkStream
_tcpclient_watcher as NetworkStreamLineWatcher
def constructor():
self._tcpclient = null
self._tcpclient_stream = null
self._watchers = []
def AddWatcher(watcher as VpnStateWatcher):
self._watchers.Add(watcher)
def NetworkStreamLineConsume(s as string):
for watcher as VpnStateWatcher in self._watchers:
watcher.VpnLogLine(s)
private def _inform_watchers():
for watcher as VpnStateWatcher in self._watchers:
watcher.VpnStateChange(self._state_text)
def connect(host as string, port as int):
try:
self._tcpclient = TcpClient(host, port)
self._tcpclient_stream = self._tcpclient.GetStream()
self._tcpclient_watcher = NetworkStreamLineWatcher(self._tcpclient_stream)
self._tcpclient_watcher.AddConsumer(self)
except e as System.Net.Sockets.SocketException:
self._tcpclient = null
self._tcpclient_stream = null
self._state_text = "Connection error (${e.Message})"
self._inform_watchers()
def disconnect():
self._tcpclient.Close()
self._tcpclient = null
self._tcpclient_stream = null
partial class MainForm(VpnStateWatcher):
vpn_model as VpnState
def constructor():
vpn_model = VpnState()
vpn_model.AddWatcher(self)
InitializeComponent() // Make the Designer bits work
def VpnStateChange(new_text as string):
self.toolStripStatusLabel.Text = new_text
def VpnLogLine(new_text as string):
print 'This line is executed'
self.textBox_log.Text += new_text
print 'This line is not'
private def MainFormLoad(sender as object, e as System.EventArgs):
pass
private def Button_refreshClick(sender as object, e as System.EventArgs):
vpn_model.connect('127.0.0.1', int.Parse(self.textBox_port.Text))
[STAThread]
def Main(argv as (string)):
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(false)
Application.Run(MainForm())