2 * This file is part of the Nice GLib ICE library.
4 * (C) 2010 Collabora Ltd.
5 * Contact: Youness Alaoui
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Nice GLib ICE library.
19 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20 * Corporation. All Rights Reserved.
23 * Youness Alaoui, Collabora Ltd.
25 * Alternatively, the contents of this file may be used under the terms of the
26 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27 * case the provisions of LGPL are applicable instead of those above. If you
28 * wish to allow use of your version of this file only under the terms of the
29 * LGPL and not to allow others to use your version of this file under the
30 * MPL, indicate your decision by deleting the provisions above and replace
31 * them with the notice and other provisions required by the LGPL. If you do
32 * not delete the provisions above, a recipient may use your version of this
33 * file under either the MPL or the LGPL.
45 #include "pseudotcp.h"
47 PseudoTcpSocket *left;
48 PseudoTcpSocket *right;
49 GMainLoop *mainloop = NULL;
55 guint right_clock = 0;
57 gboolean right_closed;
59 gboolean reading_done = FALSE;
61 static void adjust_clock (PseudoTcpSocket *sock);
63 static void write_to_sock (PseudoTcpSocket *sock)
71 len = fread (buf, 1, sizeof(buf), in);
73 g_debug ("Done reading data from file");
76 pseudo_tcp_socket_close (sock, FALSE);
79 wlen = pseudo_tcp_socket_send (sock, buf, len);
80 g_debug ("Sending %" G_GSIZE_FORMAT " bytes : %d", len, wlen);
83 if (wlen < (gint) len) {
84 g_debug ("seeking %" G_GSIZE_FORMAT " from %lu", wlen - len,
86 fseek (in, wlen - len, SEEK_CUR);
87 g_assert (!feof (in));
88 g_debug ("Socket queue full after %d bytes written", total);
96 static void opened (PseudoTcpSocket *sock, gpointer data)
98 g_debug ("Socket %p Opened", sock);
101 write_to_sock (sock);
103 pseudo_tcp_socket_send (sock, "abcdefghijklmnopqrstuvwxyz", 26);
105 pseudo_tcp_socket_close (sock, FALSE);
110 static void readable (PseudoTcpSocket *sock, gpointer data)
114 g_debug ("Socket %p Readable", sock);
117 len = pseudo_tcp_socket_recv (sock, buf, sizeof(buf));
120 g_debug ("Read %d bytes", len);
122 if (fwrite (buf, len, 1, out) == 0)
123 g_debug ("Error writing to output file");
127 g_assert_cmpint (total_wrote, <=, total_read);
128 g_debug ("Written %d bytes, need %d bytes", total_wrote, total_read);
129 if (total_wrote == total_read && feof (in)) {
130 g_assert (reading_done);
131 pseudo_tcp_socket_close (sock, FALSE);
135 if (len == 26 && strncmp (buf, "abcdefghijklmnopqrstuvwxyz", len) == 0) {
136 pseudo_tcp_socket_close (sock, FALSE);
138 g_debug ("Error reading data.. read %d bytes : %s", len, buf);
142 } else if (len == 0) {
143 pseudo_tcp_socket_close (sock, FALSE);
148 pseudo_tcp_socket_get_error (sock) != EWOULDBLOCK) {
149 g_debug ("Error reading from socket %p: %s", sock,
150 g_strerror (pseudo_tcp_socket_get_error (sock)));
155 static void writable (PseudoTcpSocket *sock, gpointer data)
157 g_debug ("Socket %p Writable", sock);
158 if (in && sock == left)
159 write_to_sock (sock);
162 static void closed (PseudoTcpSocket *sock, guint32 err, gpointer data)
164 g_error ("Socket %p Closed : %d", sock, err);
168 PseudoTcpSocket *sock;
173 static gboolean notify_packet (gpointer user_data)
175 struct notify_data *data = (struct notify_data*) user_data;
177 pseudo_tcp_socket_notify_packet (data->sock, data->buffer, data->len);
178 adjust_clock (data->sock);
184 static PseudoTcpWriteResult write_packet (PseudoTcpSocket *sock,
185 const gchar *buffer, guint32 len, gpointer user_data)
187 struct notify_data *data;
188 PseudoTcpState state;
189 int drop_rate = rand () % 100;
190 g_object_get (sock, "state", &state, NULL);
193 g_debug ("*********************Dropping packet (%d) from %p", drop_rate,
198 data = g_malloc (sizeof(struct notify_data) + len);
200 g_debug ("Socket %p(%d) Writing : %d bytes", sock, state, len);
202 memcpy (data->buffer, buffer, len);
210 g_idle_add (notify_packet, data);
216 static gboolean notify_clock (gpointer data)
218 PseudoTcpSocket *sock = (PseudoTcpSocket *)data;
219 //g_debug ("Socket %p: Notifying clock", sock);
220 pseudo_tcp_socket_notify_clock (sock);
225 static void adjust_clock (PseudoTcpSocket *sock)
229 if (pseudo_tcp_socket_get_next_clock (sock, &timeout)) {
230 timeout -= g_get_monotonic_time () / 1000;
231 g_debug ("Socket %p: Adjusting clock to %" G_GUINT64_FORMAT " ms", sock, timeout);
234 g_source_remove (left_clock);
235 left_clock = g_timeout_add (timeout, notify_clock, sock);
237 if (right_clock != 0)
238 g_source_remove (right_clock);
239 right_clock = g_timeout_add (timeout, notify_clock, sock);
242 g_debug ("Socket %p should be destroyed, it's done", sock);
247 if (left_closed && right_closed)
248 g_main_loop_quit (mainloop);
253 int main (int argc, char *argv[])
255 PseudoTcpCallbacks cbs = {
256 NULL, opened, readable, writable, closed, write_packet
259 setlocale (LC_ALL, "");
261 mainloop = g_main_loop_new (NULL, FALSE);
263 pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);
265 left_closed = right_closed = FALSE;
267 left = pseudo_tcp_socket_new (0, &cbs);
268 right = pseudo_tcp_socket_new (0, &cbs);
269 g_debug ("Left: %p. Right: %p", left, right);
271 pseudo_tcp_socket_notify_mtu (left, 1496);
272 pseudo_tcp_socket_notify_mtu (right, 1496);
274 pseudo_tcp_socket_connect (left);
276 adjust_clock (right);
279 in = fopen (argv[1], "r");
280 out = fopen (argv[2], "w");
283 g_main_loop_run (mainloop);
285 g_object_unref (left);
286 g_object_unref (right);