version 0.1.1
[sipe-libnice.git] / tests / test-pseudotcp.c
blob363fcde3d004d9de3b2505ad9f37d4a4352b5cae
1 /*
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
15 * License.
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.
22 * Contributors:
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.
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
39 #include <string.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <errno.h>
44 #include "pseudotcp.h"
46 PseudoTcpSocket *left;
47 PseudoTcpSocket *right;
48 GMainLoop *mainloop = NULL;
49 FILE *in = NULL;
50 FILE *out = NULL;
51 int total_read = 0;
52 int total_wrote = 0;
53 guint left_clock = 0;
54 guint right_clock = 0;
56 static void adjust_clock (PseudoTcpSocket *sock);
58 static void write_to_sock (PseudoTcpSocket *sock)
60 gchar buf[1024];
61 guint len;
62 guint wlen;
63 guint total = 0;
65 while (TRUE) {
66 len = fread (buf, 1, sizeof(buf), in);
67 if (len == 0) {
68 g_debug ("Done reading data from file");
69 pseudo_tcp_socket_close (sock, FALSE);
70 break;
71 } else {
72 wlen = pseudo_tcp_socket_send (sock, buf, len);
73 g_debug ("Sending %d bytes : %d", len, wlen);
74 total += wlen;
75 total_read += wlen;
76 if (wlen < len) {
77 fseek (in, wlen - len, SEEK_CUR);
78 g_debug ("Socket queue full after %d bytes written", total);
79 break;
83 adjust_clock (sock);
86 static void opened (PseudoTcpSocket *sock, gpointer data)
88 g_debug ("Socket %p Opened", sock);
89 if (sock == left) {
90 if (in)
91 write_to_sock (sock);
92 else {
93 pseudo_tcp_socket_send (sock, "abcdefghijklmnopqrstuvwxyz", 26);
94 pseudo_tcp_socket_close (sock, FALSE);
99 static void readable (PseudoTcpSocket *sock, gpointer data)
101 gchar buf[1024];
102 gint len;
103 g_debug ("Socket %p Readable", sock);
105 do {
106 len = pseudo_tcp_socket_recv (sock, buf, sizeof(buf));
108 if (len > 0) {
109 g_debug ("Read %d bytes", len);
110 if (out) {
111 if (fwrite (buf, len, 1, out) == 0)
112 g_debug ("Error writing to output file");
113 else {
114 total_wrote += len;
116 g_debug ("Written %d bytes, need %d bytes", total_wrote, total_read);
117 if (total_wrote >= total_read && feof (in)) {
118 pseudo_tcp_socket_close (left, FALSE);
119 pseudo_tcp_socket_close (right, FALSE);
122 } else {
123 if (len == 26 && strncmp (buf, "abcdefghijklmnopqrstuvwxyz", len) == 0) {
124 pseudo_tcp_socket_close (left, FALSE);
125 pseudo_tcp_socket_close (right, FALSE);
126 } else {
127 g_debug ("Error reading data.. read %d bytes : %s", len, buf);
128 exit (-1);
132 } while (len > 0);
134 if (len == -1 &&
135 pseudo_tcp_socket_get_error (sock) != EWOULDBLOCK) {
136 g_debug ("Error reading from socket : %d",
137 pseudo_tcp_socket_get_error (sock));
138 exit (-1);
141 adjust_clock (sock);
144 static void writable (PseudoTcpSocket *sock, gpointer data)
146 g_debug ("Socket %p Writable", sock);
147 if (in)
148 write_to_sock (sock);
151 static void closed (PseudoTcpSocket *sock, guint32 err, gpointer data)
153 g_debug ("Socket %p Closed : %d", sock, err);
156 struct notify_data {
157 PseudoTcpSocket *sock;
158 gchar *buffer;
159 guint32 len;
162 static gboolean notify_packet (gpointer user_data)
164 struct notify_data *data = (struct notify_data*) user_data;
165 if (!data->sock || (data->sock != left && data->sock != right))
166 return FALSE;
167 pseudo_tcp_socket_notify_packet (data->sock, data->buffer, data->len);
168 adjust_clock (data->sock);
169 g_free (data->buffer);
170 g_free (data);
171 return FALSE;
174 static PseudoTcpWriteResult write (PseudoTcpSocket *sock,
175 const gchar *buffer, guint32 len, gpointer user_data)
177 struct notify_data *data;
178 PseudoTcpState state;
179 int drop_rate = rand () % 100;
180 g_object_get (sock, "state", &state, NULL);
182 if (drop_rate < 5) {
183 g_debug ("*********************Dropping packet (%d)", drop_rate);
184 return WR_SUCCESS;
187 data = g_new0 (struct notify_data,1);
189 g_debug ("Socket %p(%d) Writing : %d bytes", sock, state, len);
191 data->buffer = g_malloc (len);
192 memcpy (data->buffer, buffer, len);
193 data->len = len;
195 if (sock == left) {
196 data->sock = right;
197 } else {
198 data->sock = left;
201 g_idle_add (notify_packet, data);
203 return WR_SUCCESS;
207 static gboolean notify_clock (gpointer data)
209 PseudoTcpSocket *sock = (PseudoTcpSocket *)data;
210 if (sock != left && sock != right)
211 return FALSE;
212 //g_debug ("Socket %p: Notifying clock", sock);
213 pseudo_tcp_socket_notify_clock (sock);
214 adjust_clock (sock);
215 return FALSE;
218 static void adjust_clock (PseudoTcpSocket *sock)
220 long timeout = 0;
221 if (pseudo_tcp_socket_get_next_clock (sock, &timeout)) {
222 //g_debug ("Socket %p: Adjuting clock to %ld ms", sock, timeout);
223 if (sock == left) {
224 if (left_clock != 0)
225 g_source_remove (left_clock);
226 left_clock = g_timeout_add (timeout, notify_clock, sock);
227 } else {
228 if (right_clock != 0)
229 g_source_remove (right_clock);
230 right_clock = g_timeout_add (timeout, notify_clock, sock);
232 } else {
233 g_debug ("Socket %p should be destroyed", sock);
234 g_object_unref (sock);
235 if (sock == left)
236 left = NULL;
237 else
238 right = NULL;
239 if (left == right)
240 g_main_loop_quit (mainloop);
245 int main (int argc, char *argv[])
247 PseudoTcpCallbacks cbs = {NULL, opened, readable, writable, closed, write};
249 mainloop = g_main_loop_new (NULL, FALSE);
251 g_type_init ();
253 pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);
255 left = pseudo_tcp_socket_new (0, &cbs);
256 right = pseudo_tcp_socket_new (0, &cbs);
257 g_debug ("Left: %p. Right: %p", left, right);
259 pseudo_tcp_socket_notify_mtu (left, 1496);
260 pseudo_tcp_socket_notify_mtu (right, 1496);
262 pseudo_tcp_socket_connect (left);
263 adjust_clock (left);
264 adjust_clock (right);
266 if (argc == 3) {
267 in = fopen (argv[1], "r");
268 out = fopen (argv[2], "w");
271 g_main_loop_run (mainloop);
273 if (in)
274 fclose (in);
275 if (out)
276 fclose (out);
278 return 0;