/* * libmaitretarot. * Copyright (C) 2002 Yves Mettier * Code taken from the MyAM project, also (c) Yves Mettier * 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 #include #include #include #include #include #include #include #include #include #include "net.h" #include "maitretarot.h" GQuark libmt_net_error_quark (void) { static GQuark q = 0; if (q == 0) q = g_quark_from_static_string ("libmt-net-error-quark"); return q; } void ignore_sigpipe (void) { struct sigaction action; action.sa_handler = SIG_IGN; sigemptyset (&(action.sa_mask)); action.sa_flags = 0; sigaction (SIGPIPE, &action, NULL); } gint libmt_make_server (guint16 port) { gchar *server_name; gint sock, res; struct sockaddr_in *myserver; struct hostent *machine_info; int optval = 1; /* What is the name of this computer ? */ if (!(server_name = (char *) g_malloc (sizeof (char) * 128))) { g_error ("Hostname malloc "); } if (gethostname (server_name, 128)) { g_error ("Hostname gethostname "); } /* Open the server socket */ sock = socket (AF_INET, SOCK_STREAM, 6); if (sock == -1) { g_error ("Socket "); } setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int)); /* Get information about the machine */ if ((machine_info = gethostbyname (server_name)) == NULL) { g_error ("gethostbyname "); } /* Creation of the server */ if ((myserver = (struct sockaddr_in *) g_malloc (sizeof (struct sockaddr_in))) == NULL) { g_error ("malloc on server creation "); } bzero (myserver, sizeof (struct sockaddr_in)); myserver->sin_family = machine_info->h_addrtype; myserver->sin_port = htons (port); myserver->sin_addr.s_addr = INADDR_ANY; res = bind (sock, (struct sockaddr *) myserver, sizeof (struct sockaddr_in)); if (res == -1) { g_error ("bind "); } res = listen (sock, 10); if (res == -1) { g_error ("listen "); } ignore_sigpipe (); return (sock); } gint libmt_connect_to_socket (gchar * ip, guint16 port, GError ** error) { struct hostent server_address, *address; struct sockaddr_in *client_sockaddr_in; gint sock; gint optval; if ((address = gethostbyname (ip)) == NULL) { g_set_error (error, LIBMT_NET_ERROR, LIBMT_NET_ERROR_GETHOSTBYNAME_FAILED, "gethostbyname failed"); return (-1); } memcpy (&server_address, address, sizeof (struct hostent)); /* Open the server socket */ if ((sock = socket (AF_INET, SOCK_STREAM, 6)) == -1) { g_set_error (error, LIBMT_NET_ERROR, LIBMT_NET_ERROR_SOCKET_CREATION_FAILED, "could not create a new socket"); return (-1); } optval = 1; setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (gint)); /* Get infos on the server */ if ((client_sockaddr_in = g_malloc (sizeof (struct sockaddr_in))) == NULL) { g_set_error (error, LIBMT_NET_ERROR, LIBMT_NET_ERROR_MEM_ALLOCATION_FAILED, "could not allocate memory for new socket"); return (-1); } client_sockaddr_in->sin_family = server_address.h_addrtype; client_sockaddr_in->sin_port = htons (port); memcpy ((gchar *) & (client_sockaddr_in->sin_addr.s_addr), server_address.h_addr, server_address.h_length); /* This works only on GNU/Linux? * bzero ((gchar *) & (client_sockaddr_in->sin_zero), sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (guint16) - sizeof (struct in_addr)); * */ /* Connect to the server as a client */ if (connect (sock, (struct sockaddr *) client_sockaddr_in, sizeof (struct sockaddr_in))) { g_free (client_sockaddr_in); g_set_error (error, LIBMT_NET_ERROR, LIBMT_NET_ERROR_SOCKET_CONNECT_FAILED, "could not connect the socket to the server"); return (-1); } g_free (client_sockaddr_in); ignore_sigpipe (); return (sock); } ssize_t libmt_read (int sock, void *buffer, size_t len) { int len_read = 0; void *p = buffer; while ((p - buffer) < len) { len_read = read (sock, p, len - (p - buffer)); if (len_read < 0) return (len_read); if (len_read == 0) return (p - buffer); p += len_read; } return (p - buffer); } ssize_t libmt_write (int sock, void *buffer, size_t len) { int len_written = 0; void *p = buffer; while ((p - buffer) < len) { len_written = write (sock, p, len - (p - buffer)); if (len_written < 0) return (len_written); if (len_written == 0) return (p - buffer); p += len_written; } return (p - buffer); } int libmt_read_packet (int sock, char *buffer, size_t max_len) { guint32 len = 0; if (libmt_read (sock, &len, sizeof (guint32)) != sizeof (guint32)) return (-1); if (len < 0) return (-1); if (len == 0) return (0); if (len > max_len) return (-1); return (libmt_read (sock, buffer, len * sizeof (char))); } int libmt_write_packet (int sock, char *buffer) { guint32 len = 0; len = strlen (buffer); if (libmt_write (sock, &len, sizeof (guint32)) != sizeof (guint32)) return (-1); return (libmt_write (sock, buffer, len * sizeof (char))); } gpointer libmt_read_data (gint sock, gint data_size) { gint len_read = 0; gpointer buffer = g_malloc (sizeof (gchar) * data_size); gpointer p = buffer; fprintf (stderr, "libmt_write_data() is obsolete\n"); while ((p - buffer) < data_size) { len_read = read (sock, p, data_size - (p - buffer)); if (len_read < 0) { g_free (buffer); return NULL; } if (len_read == 0) { g_free (buffer); return NULL; } p += len_read; } return (buffer); } gint libmt_write_data (gint sock, gpointer data, gint data_size) { gint len_written = 0; void *p = data; fprintf (stderr, "libmt_write_data() is obsolete\n"); while ((p - data) < data_size) { len_written = write (sock, p, data_size - (p - data)); if (len_written < 0) return (len_written); if (len_written == 0) return (p - data); p += len_written; } return (p - data); }