/* Echo client (async TCP)
* Copyright (C) 2000-2003 David Helder
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gnet.h>
static void async_client_connfunc (GTcpSocket* socket,
GTcpSocketConnectAsyncStatus status,
gpointer data);
static gboolean async_client_sin_iofunc (GIOChannel* iochannel,
GIOCondition condition,
gpointer data);
static gboolean async_client_in_iofunc (GIOChannel* iochannel,
GIOCondition condition,
gpointer data);
static GIOChannel* async_in;
static GIOChannel* async_sin;
static GTcpSocket* async_socket;
static int lines_pending = 0;
static gboolean read_eof = FALSE;
int
main(int argc, char** argv)
{
gchar* hostname;
gint port;
GMainLoop* main_loop;
gnet_init ();
/* Parse args */
if (argc != 3)
{
g_print ("usage: %s <server> <port>\n", argv[0]);
exit(EXIT_FAILURE);
}
hostname = argv[1];
port = atoi(argv[2]);
/* Create the main loop */
main_loop = g_main_new (FALSE);
/* Connect asynchronously */
gnet_tcp_socket_connect_async (hostname, port, async_client_connfunc, NULL);
/* Start the main loop */
g_main_run (main_loop);
exit (EXIT_SUCCESS);
return 0;
}
static void
async_client_connfunc (GTcpSocket* socket,
GTcpSocketConnectAsyncStatus status, gpointer data)
{
if (status != GTCP_SOCKET_CONNECT_ASYNC_STATUS_OK)
{
fprintf (stderr, "Error: Could not connect (status = %d)\n", status);
exit (EXIT_FAILURE);
}
async_socket = socket;
/* Read from socket */
async_sin = gnet_tcp_socket_get_io_channel (socket);
g_io_add_watch (async_sin, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
async_client_sin_iofunc, NULL);
/* Read from stdin */
async_in = g_io_channel_unix_new (fileno(stdin));
g_io_add_watch (async_in, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
async_client_in_iofunc, async_sin);
}
#include <errno.h> /* FIX */
static gboolean
async_client_sin_iofunc (GIOChannel* iochannel, GIOCondition condition,
gpointer data)
{
/* fprintf (stderr, "async_client_sin_iofunc %d\n", condition); */
/* IN/HUP/ERR */
/* Check for socket error */
if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
{
fprintf (stderr, "Error: Socket error (%d, %d)\n", condition, errno);
goto error;
}
/* Check for data to be read */
if (condition & G_IO_IN)
{
GIOError error;
gchar buffer[1024];
guint bytes_read;
/* Read the data into our buffer */
error = g_io_channel_read (iochannel, buffer,
sizeof(buffer), &bytes_read);
/* Check for stdin error */
if (error != G_IO_ERROR_NONE)
{
fprintf (stderr, "Error: Read error (%d)\n", error);
goto error;
}
/* Check for EOF */
else if (bytes_read == 0)
{
gnet_tcp_socket_delete (async_socket);
exit (EXIT_SUCCESS);
return FALSE;
}
/* Otherwise, print */
else
{
gint i;
fwrite (buffer, 1, bytes_read, stdout);
for (i = 0; i < bytes_read; ++i)
if (buffer[i] == '\n')
lines_pending--;
if (lines_pending == 0 && read_eof)
exit (EXIT_SUCCESS);
}
}
return TRUE;
error:
exit (EXIT_FAILURE);
return FALSE;
}
static gboolean
async_client_in_iofunc (GIOChannel* iochannel, GIOCondition condition,
gpointer data)
{
/* fprintf (stderr, "async_client_in_iofunc %d\n", condition); */
/* Check for input error (we check HUP last) */
if (condition & (G_IO_ERR | G_IO_NVAL))
{
fprintf (stderr, "Error: Input error\n");
goto error;
}
/* Check for data to be read (or if the stdin was closed (?)) */
if (condition & G_IO_IN)
{
GIOError error;
gchar buffer[1024];
guint bytes_read;
/* Read the data into our buffer */
error = gnet_io_channel_readline (iochannel, buffer,
sizeof(buffer), &bytes_read);
/* Check for stdin error */
if (error != G_IO_ERROR_NONE)
{
fprintf (stderr, "Error: Read error (%d)\n", error);
goto error;
}
/* Check for EOF */
else if (bytes_read == 0)
{
if (lines_pending == 0)
exit (EXIT_SUCCESS);
else
read_eof = TRUE;
return FALSE;
}
/* Otherwise, write to the socket */
else
{
GIOChannel* sin;
GIOError error;
guint bytes_written;
sin = (GIOChannel*) data;
error = gnet_io_channel_writen (sin, buffer, bytes_read,
&bytes_written);
/* g_print ("# write %d\n", bytes_written); */
g_assert (error == G_IO_ERROR_NONE);
g_assert (bytes_written == bytes_read);
lines_pending++;
}
}
if (condition & G_IO_HUP)
goto error;
return TRUE;
error:
exit (EXIT_FAILURE);
return FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1