#include <winsock2.h>

#include "glib.h"


guint source_id;
GMutex *mutex;
GCond *cond;


gboolean
recv_cb (GIOChannel *source,
	 GIOCondition condition,
	 gpointer data)
{
  g_assert_not_reached ();
}

gboolean
send_cb (GIOChannel *source,
	 GIOCondition condition,
	 gpointer data)
{
  gboolean is_second = (gboolean) data;
  GIOStatus status;
  gsize bytes_written;
  gchar c = 'T';

  status = g_io_channel_write_chars (source, &c, 1, &bytes_written, NULL);
  g_print ("%s send_cb write char, status: %d.\n",
	   (is_second ? "Second" : "First"),
	   status);

  g_source_remove (source_id);

  source_id = g_io_add_watch (source,
			      G_IO_IN | G_IO_ERR,
			      recv_cb,
			      NULL);

  g_mutex_lock (mutex);
  g_cond_signal (cond);
  g_mutex_unlock (mutex);

  return (TRUE);
}

int
main (int argc, char **argv)
{
  WSADATA wsa_data;
  SOCKET s;
  struct sockaddr_in addr;
  gint addrlen = sizeof (addr);

  GIOChannel *channel;
  GMainLoop *loop;
  GThread *thread;
  
  g_assert (WSAStartup(0x0202, &wsa_data) == 0);
  g_thread_init (NULL);

  mutex = g_mutex_new ();
  cond = g_cond_new ();
  
  s = socket (AF_INET, SOCK_STREAM, 0);
  g_assert (s != INVALID_SOCKET);
  
  g_assert (WSAStringToAddress ("127.0.0.1:5555",
				AF_INET,
				NULL,
				(PSOCKADDR)&addr,
				&addrlen)
	    != SOCKET_ERROR);

  g_assert (connect (s, (struct sockaddr *) &addr, sizeof (addr)) != SOCKET_ERROR);

  channel = g_io_channel_win32_new_socket (s);

  loop = g_main_loop_new (NULL, FALSE);
  g_assert (loop);

  thread = g_thread_create ((GThreadFunc) g_main_loop_run,
			    loop,
			    TRUE,
			    NULL);
  g_assert (thread);


  g_mutex_lock (mutex);
  source_id = g_io_add_watch (channel,
			      G_IO_IN | G_IO_ERR | G_IO_OUT,
			      send_cb,
			      (gpointer) FALSE);
  g_cond_wait (cond, mutex);
  g_mutex_unlock (mutex);

  g_usleep (500000);

  g_source_remove (source_id);

  g_usleep (500000);

  g_mutex_lock (mutex);
  source_id = g_io_add_watch (channel,
			      G_IO_IN | G_IO_ERR | G_IO_OUT,
			      send_cb,
			      (gpointer) TRUE);
  g_cond_wait (cond, mutex);
  g_mutex_unlock (mutex);

  g_main_loop_quit (loop);
  g_thread_join (thread);

  return (0);
}

