[Mono-list] assertion g_utf8_validate failed

Mario Fuentes mario@gnome.cl
Fri, 12 Nov 2004 11:44:51 -0300


--=-Q3Awd2kKiiwpw6VkCLwl
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

El vie, 12-11-2004 a las 06:51 -0500, Jonathan Pryor escribió:
[...]
> Instead, use GLib.Timeout.Add (with a small timeout) or
> Gtk.ThreadNotify.  You can pass each of these a delegate, which will be
> invoked from the GTK+ UI thread, so you don't need to worry about
> locking/unlocking the application, cleaning up your code, and
> maintaining your sanity.
> 
Thanks, I rewrite my sample, and now *seems* it's OK.  I attach my
sample for to receive feedback. :D

>  - Jon

Bye guys.
-- 
Mario Fuentes
http://primate.gnome.cl/~mario
mailto:mario@gnome.cl

--=-Q3Awd2kKiiwpw6VkCLwl
Content-Disposition: attachment; filename=Chat.cs
Content-Type: text/x-csharp; name=Chat.cs; charset=utf-8
Content-Transfer-Encoding: 7bit

// Mario Fuentes <mario@gnome.cl>
// Compile: mcs -pkg:gtk-sharp Chat.cs
namespace Samples {
	using System;
	using System.Text;
	using System.Collections;
	using System.Net;
	using SNS = System.Net.Sockets;
	using System.IO;
	using System.Threading;
	using Gtk;

	public delegate void NetEventHandler (NetEventType type, string text);
	public enum NetEventType
	{
		Connected,
		NewMessage,
	}
	
	public class Net
	{
#region Packet
		internal class Packet {
			internal byte [] buffer;
			internal SNS.Socket socket;
			
			internal Packet (int size, SNS.Socket sock)
			{
				buffer = new byte[size];
				socket = sock;
			}
		}
#endregion
		
		// Default Port
		const int DEFAULT_PORT = 9999;

		// Notification Event
		public event NetEventHandler NetEvent = null;
		// Flags
		bool started = false;
		bool isConnected = false;
		public bool IsConnected { get { return isConnected; } }
		bool isServer = false;
		bool done = false;
		
		// UserName
		string userName;
		
		// Host Name
		string host = null;
		// Socket
		SNS.Socket sock = null;
		SNS.Socket srvSock = null;
		
		Queue inbox;
		
		byte [] buffer = null;
		
		Packet pack = null;
		
		// Instance a server
		public Net ()
		{
			isServer = true;
			Init ();
		}
		// Instance a client
		public Net (string host)
		{
			this.host = host;
			Init ();
		}
		
		void Init ()
		{
			userName = System.Environment.UserName;
			inbox = new Queue ();
			GLib.Timeout.Add (100, new GLib.TimeoutHandler (TimeoutFunc));
			CreateSocket ();
		}

		// Check for new messages
		bool TimeoutFunc ()
		{
			if (isConnected)
			{
				if (!started)
				{
					if (NetEvent != null)
						NetEvent (NetEventType.Connected, null);
					started = true;
				}
				
				if (inbox.Count > 0)
				{
					string str = inbox.Dequeue () as string;
					if (NetEvent != null)
						NetEvent (NetEventType.NewMessage, str);
				}
			}
			
			return !done;
		}
		
		void CreateSocket ()
		{
			IPAddress ipAddress;
			if (isServer)
				ipAddress = IPAddress.Any;
			else
				ipAddress = Dns.Resolve (host).AddressList[0];
			
			IPEndPoint ipEndPoint = new IPEndPoint (ipAddress, DEFAULT_PORT);
			sock = new SNS.Socket (SNS.AddressFamily.InterNetwork,
			                                  SNS.SocketType.Stream,
			                                  SNS.ProtocolType.Tcp);
			
			if (isServer)
			{
				sock.Bind (ipEndPoint);
				sock.Listen (1);
				sock.BeginAccept (new AsyncCallback (OnConnectCallback), sock);
			}
			else
			{
				sock.BeginConnect (ipEndPoint,
					new AsyncCallback (OnConnectCallback), sock);
			}
		}
		
		void OnConnectCallback (IAsyncResult ar)
		{
			SNS.Socket socket = (SNS.Socket) ar.AsyncState;
			SNS.Socket serverSock = null;
			Console.Write ("OnConnectCallback.... ");
			if (isServer)
			{
				serverSock = socket.EndAccept (ar);
				srvSock = serverSock;
				if (serverSock.Connected == false)
					return;
				socket.Close ();
			}
			else
			{
				socket.EndConnect (ar);
				if (socket.Connected == false)
					return;
			}
			Console.WriteLine ("Connected!");
			isConnected = true;
						
			SNS.Socket s = (isServer) ? serverSock : socket;
			s.Blocking = false;
			
			WaitForData (s);
		}
		
		void WaitForData (SNS.Socket s)
		{
			pack = new Packet (256, s);
			
			s.BeginReceive (pack.buffer, 0, pack.buffer.Length,
				SNS.SocketFlags.None, new AsyncCallback (this.OnDataReceive), pack);
		}
		
		void OnDataReceive (IAsyncResult ar)
		{
			Packet packet = ar.AsyncState as Packet;
			int len = packet.socket.EndReceive (ar);

			string strRec = Encoding.UTF8.GetString (packet.buffer);
			inbox.Enqueue (strRec);
			
			WaitForData (packet.socket);
		}
		
		void OnDataSend (IAsyncResult ar)
		{
			string text = ar.AsyncState as String;
			inbox.Enqueue (text);
		}
		
		public void Send (string str)
		{
			string strSend = userName + "> " + str;
			byte [] buf = Encoding.UTF8.GetBytes (strSend);
			
			Packet packet = new Packet (0, pack.socket);
			packet.socket.BeginSend (buf, 0, buf.Length,
				SNS.SocketFlags.None, new AsyncCallback (OnDataSend), strSend);
		}
	}
	
	public class Chat : Window
	{
		// GUI
		Entry entHost;
		Button btnConnect;
		Button btnCreate;
		ScrolledWindow scrollChat;
		TextView textChat;
		Entry entChat;
		
		// Network
		Net net;
		
		public Chat () : base (WindowType.Toplevel)
		{
			// Setup window properties
			this.Title = "Chat";
			this.BorderWidth = 12;
			this.DeleteEvent += OnDeleteEvent;
			// Add a vertical box
			VBox box = new VBox (false, 6);
			// Pack box on the window
			this.Add (box);
			// Create a table for packing controls
			Table table = new Table (3, 2, false);
			table.RowSpacing = 3;
			table.ColumnSpacing = 6;
			// Pack table on the box
			box.PackStart (table, false, false, 0);
			// Pack a label on the table
			table.Attach (new Label ("Host:"), 0, 1, 0, 1);
			// Create and pack a entre con the table, for get hostname from user
			entHost = new Entry ();
			table.Attach (entHost, 1, 2, 0, 1);
			// A button for try connect to "Host"
			btnConnect = new Button ("Connect");
			btnConnect.Clicked += OnBtnConnectClicked;
			table.Attach (btnConnect, 2, 3, 0, 1);
			// A button for create a server (listen for a user)
			btnCreate = new Button ("Create a server!");
			btnCreate.Clicked += OnBtnCreateClicked;
			table.Attach (btnCreate, 0, 3, 1, 2);
			// A scrolled window container for pack the textview
			scrollChat = new ScrolledWindow ();
			scrollChat.ShadowType = ShadowType.In;
			// Pack on the box
			box.PackStart (scrollChat);
			// TextView for view send/receive text			
			textChat = new TextView ();
			textChat.Editable = false;
			textChat.WrapMode = WrapMode.Word;
			// Pack text into scroll
			scrollChat.Add (textChat);
			// A entry for user text
			entChat = new Entry ();
			entChat.Activated += OnEntChatActivated;
			box.PackStart (entChat, false, false, 0);
			// Show the windows and all widgets/controls contained
			this.ShowAll ();
	
		}
		
		void AppendText (string text)
		{
			textChat.Buffer.Text += text;
			textChat.Buffer.Text += System.Environment.NewLine;
			scrollChat.Vadjustment.Value = scrollChat.Vadjustment.Upper;
		}
		
		void SetSensitive (bool b)
		{
			entHost.Sensitive = b;
			btnConnect.Sensitive = b;
			btnCreate.Sensitive = b;
		}
		
		
		void ConnectTo (string host)
		{
			if (host == null)
				net = new Net ();
			else
				net = new Net (entHost.Text);
			
			net.NetEvent += OnNetEvent;
			
			SetSensitive (false);
		}
		
		void OnNetEvent (NetEventType t, string s)
		{
			switch (t)
			{
				case NetEventType.Connected:
					AppendText ("** Connected **");
					break;
				case NetEventType.NewMessage:
					AppendText (s);
					break;
			}
		}
		
#region Callbacks from the GUI
		void OnDeleteEvent (object o, DeleteEventArgs args)
		{
			// Disconnect
			// TODO
			
			// Stop GTK loop
			args.RetVal = true;
			Application.Quit ();
		}
		
		void OnBtnConnectClicked (object o, EventArgs args)
		{
			if (entHost.Text == String.Empty)
			{
				AppendText ("** Host is empty **");
				return;
			}
			
			ConnectTo (entHost.Text);
		}
		
		void OnBtnCreateClicked (object o, EventArgs args)
		{
			ConnectTo (null);
		}
		
		void OnEntChatActivated (object o, EventArgs args)
		{
			if (entChat.Text == String.Empty)
				return;
			
			if ((net == null) || !net.IsConnected)
			{
				AppendText ("** You aren't connected **");
				return;
			}
			
			net.Send (entChat.Text);
			entChat.Text = String.Empty;
		}
#endregion
	
		public static void Main (string [] args)
		{
			Application.Init ();
			new Chat ();
			Application.Run ();
		}
	}
}

--=-Q3Awd2kKiiwpw6VkCLwl--