298 lines
7.4 KiB
C
298 lines
7.4 KiB
C
|
/*
|
|||
|
* tools
|
|||
|
* Cr<EFBFBD>ation et manipulation de sockets
|
|||
|
* Thomas Nemeth -- le 15 juin 2001
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <unistd.h>
|
|||
|
#include <errno.h>
|
|||
|
#include <signal.h>
|
|||
|
#include <netdb.h>
|
|||
|
#include <sys/types.h>
|
|||
|
#include <sys/socket.h>
|
|||
|
#include <netinet/in.h>
|
|||
|
#include <string.h>
|
|||
|
#include <strings.h>
|
|||
|
#include <arpa/inet.h>
|
|||
|
#include "defines.h"
|
|||
|
#include "xmem.h"
|
|||
|
#include "tools.h"
|
|||
|
|
|||
|
/*
|
|||
|
* Ouverture d'une socket de type flot de donn<EFBFBD>es
|
|||
|
*
|
|||
|
* cr<EFBFBD>ation d'une socket serveur : port != 0
|
|||
|
*
|
|||
|
*/
|
|||
|
int ouvre_socket (int port, char *adr_ip, struct sockaddr_in *ptr_adresse) {
|
|||
|
int desc_soc;
|
|||
|
int lg_adresse = sizeof (struct sockaddr_in);
|
|||
|
int lg_linger = sizeof (struct linger);
|
|||
|
struct sockaddr_in adresse;
|
|||
|
struct linger ling;
|
|||
|
|
|||
|
/*
|
|||
|
* Cr<EFBFBD>ation de la socket
|
|||
|
*
|
|||
|
*/
|
|||
|
if ( (desc_soc = socket (AF_INET, SOCK_STREAM, 0) ) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Ne peut pas ouvrir la socket de connexion.\n");
|
|||
|
#endif
|
|||
|
perror (__FILE__ " socket");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Affectation des options
|
|||
|
*
|
|||
|
*/
|
|||
|
if (port != 0) {
|
|||
|
int opt = 1;
|
|||
|
if (setsockopt (desc_soc, SOL_SOCKET,
|
|||
|
SO_REUSEADDR, &opt, sizeof (int) ) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Impossible de positionner REUSEADDR.\n");
|
|||
|
#endif
|
|||
|
perror (__FILE__ " setsockopt -- REUSEADDR");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
ling.l_onoff = 0;
|
|||
|
ling.l_linger = 0;
|
|||
|
if (setsockopt (desc_soc, SOL_SOCKET, SO_LINGER, &ling, lg_linger) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Impossible de positionner LINGER.\n");
|
|||
|
#endif
|
|||
|
perror (__FILE__ " setsockopt -- LINGER");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Pr<EFBFBD>paration de l'adresse d'attachement
|
|||
|
*
|
|||
|
*/
|
|||
|
memset (&adresse, 0, sizeof (adresse) );
|
|||
|
adresse.sin_family = AF_INET;
|
|||
|
if (adr_ip) {
|
|||
|
struct in_addr ia;
|
|||
|
|
|||
|
if (inet_aton(adr_ip, &ia)) {
|
|||
|
adresse.sin_addr = ia;
|
|||
|
} else {
|
|||
|
struct hostent *h;
|
|||
|
|
|||
|
h = gethostbyname(adr_ip);
|
|||
|
if (!h) {
|
|||
|
fprintf (stderr, "Adresse %s inconnue.\n", adr_ip);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
memcpy (&adresse.sin_addr.s_addr, h->h_addr, h->h_length);
|
|||
|
}
|
|||
|
} else
|
|||
|
adresse.sin_addr.s_addr = htonl (INADDR_ANY);
|
|||
|
adresse.sin_port = htons (port);
|
|||
|
|
|||
|
/*
|
|||
|
* Demande d'attachement de la socket
|
|||
|
*
|
|||
|
*/
|
|||
|
if (bind (desc_soc, (struct sockaddr*) &adresse, lg_adresse) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr,
|
|||
|
"Ne peut donner de nom <20> la socket de connexion.\n"
|
|||
|
"Attendez quelques minutes avant de relancer.\n");
|
|||
|
#endif
|
|||
|
perror (__FILE__ " bind");
|
|||
|
close (desc_soc);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* R<EFBFBD>cup<EFBFBD>ration de l'adresse effective d'attachement
|
|||
|
*
|
|||
|
*/
|
|||
|
if (ptr_adresse != NULL)
|
|||
|
getsockname (desc_soc, (struct sockaddr *) ptr_adresse, &lg_adresse);
|
|||
|
|
|||
|
return desc_soc;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int connect_server (const char *machine, int port) {
|
|||
|
struct hostent *serveur;
|
|||
|
struct sockaddr_in adresse_serveur, adresse_client;
|
|||
|
int socket_client;
|
|||
|
|
|||
|
/* Recherche de la machine o<> se trouve le serveur */
|
|||
|
if ( (serveur = gethostbyname (machine) ) == NULL) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Machine %s inconnue...\n", machine);
|
|||
|
#endif
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/* Cr<43>ation et attachement de la socket du client --
|
|||
|
* port quelconque => 0
|
|||
|
*/
|
|||
|
if ( (socket_client = ouvre_socket
|
|||
|
(0, NULL, (struct sockaddr_in *) &adresse_client)) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Cr<EFBFBD>ation de la socket du client impossible.\n");
|
|||
|
#endif
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/* Pr<50>paration de l'adresse du serveur */
|
|||
|
adresse_serveur.sin_family = AF_INET;
|
|||
|
adresse_serveur.sin_port = htons (port);
|
|||
|
memcpy (&adresse_serveur.sin_addr.s_addr,
|
|||
|
serveur->h_addr, serveur->h_length);
|
|||
|
|
|||
|
/* Demande de connexion au serveur */
|
|||
|
if (connect (socket_client, (struct sockaddr *) &adresse_serveur,
|
|||
|
sizeof (adresse_serveur) ) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Impossible de se connecter au serveur.\n");
|
|||
|
#endif
|
|||
|
perror (__FILE__ " connect");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
return socket_client;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int install_server (int port, char *adr_ip, struct sockaddr_in *ecoute) {
|
|||
|
int socket_ecoute;
|
|||
|
|
|||
|
/* Ouverture de la socket */
|
|||
|
if ( (socket_ecoute = ouvre_socket (port, adr_ip, ecoute)) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Cr<EFBFBD>ation de la socket du serveur impossible.\n");
|
|||
|
#endif
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/* D<>claration d'ouverture du service */
|
|||
|
if (listen (socket_ecoute, 10) == -1) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Impossible d'enregistrer le service.\n");
|
|||
|
#endif
|
|||
|
perror (__FILE__ " listen");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
return socket_ecoute;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Fonction de r<EFBFBD>ception de donn<EFBFBD>es
|
|||
|
*
|
|||
|
*/
|
|||
|
int read_infos (int socket_data, char *infos) {
|
|||
|
int nb;
|
|||
|
|
|||
|
/* SSIZE_MAX = 2147483647 */
|
|||
|
memset (infos, 0, MAXSTRLEN);
|
|||
|
nb = read (socket_data, infos, MAXSTRLEN - 1);
|
|||
|
|
|||
|
if ( (nb == -1) || (nb == 0) ) {
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Erreur de connexion r<>ception !\n");
|
|||
|
#endif
|
|||
|
if ( (errno == EPIPE) || (nb == 0) ) return FALSE; /* cont = FALSE; */
|
|||
|
}
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
printf ("Re<EFBFBD>u : [%s] lg = %d/%d\n", infos, strlen (infos), nb);
|
|||
|
#endif
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Fonction d'<EFBFBD>misson de donn<EFBFBD>es
|
|||
|
*
|
|||
|
*/
|
|||
|
int send_infos (int socket_data, const char *infos) {
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
printf ("<EFBFBD>mission de : %s [%d]\n", infos, strlen (infos));
|
|||
|
#endif
|
|||
|
|
|||
|
if (write (socket_data, (void *) infos, strlen (infos) + 1) == -1) {
|
|||
|
/* Erreur : plus de socket ! */
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "Erreur de connexion <20>mission !\n");
|
|||
|
#endif
|
|||
|
if (errno == EPIPE) return FALSE; /*cont = FALSE;*/
|
|||
|
}
|
|||
|
#ifdef DEBUG
|
|||
|
fprintf (stderr, "<EFBFBD>mission ok !\n");
|
|||
|
#endif
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void get_sock_infos (int sock, char **nom, char **adr, int *prl, int *prd) {
|
|||
|
struct sockaddr_in name;
|
|||
|
#ifdef OpenBSD
|
|||
|
int namelen;
|
|||
|
#else
|
|||
|
socklen_t namelen;
|
|||
|
#endif
|
|||
|
struct hostent *machine;
|
|||
|
|
|||
|
/* Initialisations en cas d'<27>checs */
|
|||
|
*nom = NULL;
|
|||
|
*adr = NULL;
|
|||
|
*prd = 0;
|
|||
|
|
|||
|
/* Infos locales (port) */
|
|||
|
namelen = sizeof (name);
|
|||
|
if (getsockname (sock, (struct sockaddr *) &name, &namelen) == 0)
|
|||
|
*prl = ntohs (name.sin_port);
|
|||
|
else {
|
|||
|
perror ("getsockname() ");
|
|||
|
*prl = 0;
|
|||
|
}
|
|||
|
|
|||
|
/* Port et adresse IP distants */
|
|||
|
namelen = sizeof (name);
|
|||
|
if (getpeername (sock, (struct sockaddr *) &name, &namelen) != 0) {
|
|||
|
#ifdef DEBUG
|
|||
|
perror ("Erreur de r<>cup<75>ration d'information sur pair !\n"
|
|||
|
"getpeername() ");
|
|||
|
#else
|
|||
|
perror ("Impossible d'obtenir les infos distantes ");
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
*adr = xstrdup (inet_ntoa (name.sin_addr));
|
|||
|
*prd = ntohs (name.sin_port);
|
|||
|
|
|||
|
/* Nom de machine distante */
|
|||
|
machine = gethostbyaddr ((char *)&name.sin_addr,
|
|||
|
sizeof name.sin_addr, name.sin_family);
|
|||
|
if (machine == NULL) {
|
|||
|
#ifdef DEBUG
|
|||
|
perror ("Erreur de r<>cup<75>ration de nom de pair.\n"
|
|||
|
"gethostbyaddr() ");
|
|||
|
fprintf (stderr, "Adresse : %s (%s)\tFamille : %d (2 == AF_INET)\n",
|
|||
|
*adr, (char *)&name.sin_addr, name.sin_family);
|
|||
|
#else
|
|||
|
perror ("Impossible d'obtenir le nom d'h<>te distant ");
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
*nom = xstrdup (machine->h_name);
|
|||
|
}
|