PseudoTcpChannel *
pseudo_tcp_channel_new(int unreliable_socket,
                       int conn_id)
{
	PseudoTcpChannel *tcp = (PseudoTcpChannel *) malloc(sizeof(PseudoTcpChannel));
	memset(tcp, 0, sizeof(PseudoTcpChannel));
	
	if(socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC, tcp->reliable_sockets) != 0) {
		free(tcp);
		return NULL;
	}

	PseudoTcpCallbacks callbacks;
	callbacks.user_data = tcp;
	callbacks.PseudoTcpOpened = opened;
	callbacks.PseudoTcpReadable = readable;
	callbacks.PseudoTcpWritable = writable;
	callbacks.PseudoTcpClosed = closed;
	callbacks.PseudoTcpWriteResult = needs_write;
	tcp->pseudo_tcp = pseudo_tcp_socket_new(conn_id, &callbacks);

	pseudo_tcp_socket_notify_mtu(tcp->pseudo_tcp, 1400);

	tcp->on_connected = signal_new();
	tcp->on_data_received = signal_new();
	tcp->on_closed = signal_new();

	return tcp;
}
int main (int argc, char *argv[])
{
  PseudoTcpCallbacks cbs = {
    NULL, opened, readable, writable, closed, write_packet
  };

  setlocale (LC_ALL, "");

  mainloop = g_main_loop_new (NULL, FALSE);

  g_type_init ();

  pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);

  left_closed = right_closed = FALSE;

  left = pseudo_tcp_socket_new (0, &cbs);
  right = pseudo_tcp_socket_new (0, &cbs);
  g_debug ("Left: %p. Right: %p", left, right);

  pseudo_tcp_socket_notify_mtu (left, 1496);
  pseudo_tcp_socket_notify_mtu (right, 1496);

  pseudo_tcp_socket_connect (left);
  adjust_clock (left);
  adjust_clock (right);

  if (argc == 3) {
    in = fopen (argv[1], "r");
    out = fopen (argv[2], "w");
  }

  g_main_loop_run (mainloop);

  g_object_unref (left);
  g_object_unref (right);

  if (in)
    fclose (in);
  if (out)
    fclose (out);

  return 0;
}
int main (int argc, char *argv[])
{
  PseudoTcpCallbacks cbs = {
    NULL, opened, readable, writable, closed, write_packet
  };
  GOptionContext *context;
  GError *error = NULL;

  setlocale (LC_ALL, "");
  g_type_init ();

  /* Configuration. */
  context = g_option_context_new ("— fuzz-test the pseudotcp socket");
  g_option_context_add_main_entries (context, entries, NULL);

  if (!g_option_context_parse (context, &argc, &argv, &error)) {
    g_printerr ("Option parsing failed: %s\n", error->message);
    goto context_error;
  }

  if (n_changes_lambda == 0) {
    g_printerr ("Option parsing failed: %s\n",
        "Lambda values must be positive.");
    goto context_error;
  }

  g_option_context_free (context);

  /* Tweak the configuration. */
  if (seed == 0) {
    seed = g_get_real_time ();
  }

  /* Open the input and output files */
  if (argc >= 3) {
    in = fopen (argv[1], "r");
    out = fopen (argv[2], "w");
  }

  /* Set up the main loop and sockets. */
  main_loop = g_main_loop_new (NULL, FALSE);

  g_print ("Using seed: %" G_GINT64_FORMAT ", start position: %u, λ: %u\n",
      seed, fuzz_start_pos, n_changes_lambda);
  prng = g_rand_new_with_seed (seed);

  pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);

  left = pseudo_tcp_socket_new (0, &cbs);
  right = pseudo_tcp_socket_new (0, &cbs);
  g_debug ("Left: %p. Right: %p", left, right);

  pseudo_tcp_socket_notify_mtu (left, 1496);
  pseudo_tcp_socket_notify_mtu (right, 1496);

  pseudo_tcp_socket_connect (left);
  adjust_clock (left);
  adjust_clock (right);

  /* Run the main loop. */
  g_main_loop_run (main_loop);
  g_main_loop_unref (main_loop);

  g_object_unref (left);
  g_object_unref (right);

  g_rand_free (prng);

  if (in != NULL)
    fclose (in);
  if (out != NULL)
    fclose (out);

  return retval;

context_error:
  g_printerr ("\n%s\n", g_option_context_get_help (context, TRUE, NULL));
  g_option_context_free (context);

  return 1;
}