Comment servir des pintes de Guinness "over Internet" ;) Reprise/Fork d'un très ancien code d'un pilier de f.m.b.l : http://tnemeth.free.fr/projets/guinness-server.html
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tools.c 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * tools
  3. * Creation et manipulation de sockets
  4. * Thomas Nemeth -- le 15 juin 2001
  5. *
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <errno.h>
  11. #include <signal.h>
  12. #include <netdb.h>
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <netinet/in.h>
  16. #include <string.h>
  17. #include <strings.h>
  18. #include <arpa/inet.h>
  19. #include "defines.h"
  20. #include "xmem.h"
  21. #include "tools.h"
  22. /*
  23. * Ouverture d'une socket de type flot de donnees
  24. *
  25. * creation d'une socket serveur : port != 0
  26. *
  27. */
  28. int ouvre_socket (int port, char *adr_ip, struct sockaddr_in *ptr_adresse) {
  29. int desc_soc;
  30. int lg_adresse = sizeof (struct sockaddr_in);
  31. int lg_linger = sizeof (struct linger);
  32. struct sockaddr_in adresse;
  33. struct linger ling;
  34. /*
  35. * Creation de la socket
  36. *
  37. */
  38. if ( (desc_soc = socket (AF_INET, SOCK_STREAM, 0) ) == -1) {
  39. #ifdef DEBUG
  40. fprintf (stderr, "Ne peut pas ouvrir la socket de connexion.\n");
  41. #endif
  42. perror (__FILE__ " socket");
  43. return -1;
  44. }
  45. /*
  46. * Affectation des options
  47. *
  48. */
  49. if (port != 0) {
  50. int opt = 1;
  51. if (setsockopt (desc_soc, SOL_SOCKET,
  52. SO_REUSEADDR, &opt, sizeof (int) ) == -1) {
  53. #ifdef DEBUG
  54. fprintf (stderr, "Impossible de positionner REUSEADDR.\n");
  55. #endif
  56. perror (__FILE__ " setsockopt -- REUSEADDR");
  57. return -1;
  58. }
  59. }
  60. ling.l_onoff = 0;
  61. ling.l_linger = 0;
  62. if (setsockopt (desc_soc, SOL_SOCKET, SO_LINGER, &ling, lg_linger) == -1) {
  63. #ifdef DEBUG
  64. fprintf (stderr, "Impossible de positionner LINGER.\n");
  65. #endif
  66. perror (__FILE__ " setsockopt -- LINGER");
  67. return -1;
  68. }
  69. /*
  70. * Preparation de l'adresse d'attachement
  71. *
  72. */
  73. memset (&adresse, 0, sizeof (adresse) );
  74. adresse.sin_family = AF_INET;
  75. if (adr_ip) {
  76. struct in_addr ia;
  77. if (inet_aton(adr_ip, &ia)) {
  78. adresse.sin_addr = ia;
  79. } else {
  80. struct hostent *h;
  81. h = gethostbyname(adr_ip);
  82. if (!h) {
  83. fprintf (stderr, "Adresse %s inconnue.\n", adr_ip);
  84. return -1;
  85. }
  86. memcpy (&adresse.sin_addr.s_addr, h->h_addr, h->h_length);
  87. }
  88. } else
  89. adresse.sin_addr.s_addr = htonl (INADDR_ANY);
  90. adresse.sin_port = htons (port);
  91. /*
  92. * Demande d'attachement de la socket
  93. *
  94. */
  95. if (bind (desc_soc, (struct sockaddr*) &adresse, lg_adresse) == -1) {
  96. #ifdef DEBUG
  97. fprintf (stderr,
  98. "Ne peut donner de nom a la socket de connexion.\n"
  99. "Attendez quelques minutes avant de relancer.\n");
  100. #endif
  101. perror (__FILE__ " bind");
  102. close (desc_soc);
  103. return -1;
  104. }
  105. /*
  106. * Recuperation de l'adresse effective d'attachement
  107. *
  108. */
  109. if (ptr_adresse != NULL)
  110. getsockname (desc_soc, (struct sockaddr *) ptr_adresse, &lg_adresse);
  111. return desc_soc;
  112. }
  113. int connect_server (const char *machine, int port) {
  114. struct hostent *serveur;
  115. struct sockaddr_in adresse_serveur, adresse_client;
  116. int socket_client;
  117. /* Recherche de la machine ou se trouve le serveur */
  118. if ( (serveur = gethostbyname (machine) ) == NULL) {
  119. #ifdef DEBUG
  120. fprintf (stderr, "Machine %s inconnue...\n", machine);
  121. #endif
  122. return -1;
  123. }
  124. /* Creation et attachement de la socket du client --
  125. * port quelconque => 0
  126. */
  127. if ( (socket_client = ouvre_socket
  128. (0, NULL, (struct sockaddr_in *) &adresse_client)) == -1) {
  129. #ifdef DEBUG
  130. fprintf (stderr, "Creation de la socket du client impossible.\n");
  131. #endif
  132. return -1;
  133. }
  134. /* Preparation de l'adresse du serveur */
  135. adresse_serveur.sin_family = AF_INET;
  136. adresse_serveur.sin_port = htons (port);
  137. memcpy (&adresse_serveur.sin_addr.s_addr,
  138. serveur->h_addr, serveur->h_length);
  139. /* Demande de connexion au serveur */
  140. if (connect (socket_client, (struct sockaddr *) &adresse_serveur,
  141. sizeof (adresse_serveur) ) == -1) {
  142. #ifdef DEBUG
  143. fprintf (stderr, "Impossible de se connecter au serveur.\n");
  144. #endif
  145. perror (__FILE__ " connect");
  146. return -1;
  147. }
  148. return socket_client;
  149. }
  150. int install_server (int port, char *adr_ip, struct sockaddr_in *ecoute) {
  151. int socket_ecoute;
  152. /* Ouverture de la socket */
  153. if ( (socket_ecoute = ouvre_socket (port, adr_ip, ecoute)) == -1) {
  154. #ifdef DEBUG
  155. fprintf (stderr, "Creation de la socket du serveur impossible.\n");
  156. #endif
  157. return -1;
  158. }
  159. /* Declaration d'ouverture du service */
  160. if (listen (socket_ecoute, 10) == -1) {
  161. #ifdef DEBUG
  162. fprintf (stderr, "Impossible d'enregistrer le service.\n");
  163. #endif
  164. perror (__FILE__ " listen");
  165. return -1;
  166. }
  167. return socket_ecoute;
  168. }
  169. /*
  170. * Fonction de reception de donnees
  171. *
  172. */
  173. int read_infos (int socket_data, char *infos) {
  174. int nb;
  175. /* SSIZE_MAX = 2147483647 */
  176. memset (infos, 0, MAXSTRLEN);
  177. nb = read (socket_data, infos, MAXSTRLEN - 1);
  178. if ( (nb == -1) || (nb == 0) ) {
  179. #ifdef DEBUG
  180. fprintf (stderr, "Erreur de connexion reception !\n");
  181. #endif
  182. if ( (errno == EPIPE) || (nb == 0) ) return FALSE; /* cont = FALSE; */
  183. }
  184. #ifdef DEBUG
  185. printf ("Recu : [%s] lg = %d/%d\n", infos, strlen (infos), nb);
  186. #endif
  187. return TRUE;
  188. }
  189. /*
  190. * Fonction d'emisson de donnees
  191. *
  192. */
  193. int send_infos (int socket_data, const char *infos) {
  194. #ifdef DEBUG
  195. printf ("Emission de : %s [%d]\n", infos, strlen (infos));
  196. #endif
  197. if (write (socket_data, (void *) infos, strlen (infos) + 1) == -1) {
  198. /* Erreur : plus de socket ! */
  199. #ifdef DEBUG
  200. fprintf (stderr, "Erreur de connexion emission !\n");
  201. #endif
  202. if (errno == EPIPE) return FALSE; /*cont = FALSE;*/
  203. }
  204. #ifdef DEBUG
  205. fprintf (stderr, "Emission ok !\n");
  206. #endif
  207. return TRUE;
  208. }
  209. void get_sock_infos (int sock, char **nom, char **adr, int *prl, int *prd) {
  210. struct sockaddr_in name;
  211. #ifdef OpenBSD
  212. int namelen;
  213. #else
  214. socklen_t namelen;
  215. #endif
  216. struct hostent *machine;
  217. /* Initialisations en cas d'echecs */
  218. *nom = NULL;
  219. *adr = NULL;
  220. *prd = 0;
  221. /* Infos locales (port) */
  222. namelen = sizeof (name);
  223. if (getsockname (sock, (struct sockaddr *) &name, &namelen) == 0)
  224. *prl = ntohs (name.sin_port);
  225. else {
  226. perror ("getsockname() ");
  227. *prl = 0;
  228. }
  229. /* Port et adresse IP distants */
  230. namelen = sizeof (name);
  231. if (getpeername (sock, (struct sockaddr *) &name, &namelen) != 0) {
  232. #ifdef DEBUG
  233. perror ("Erreur de recuperation d'information sur pair !\n"
  234. "getpeername() ");
  235. #else
  236. perror ("Impossible d'obtenir les infos distantes ");
  237. #endif
  238. return;
  239. }
  240. *adr = xstrdup (inet_ntoa (name.sin_addr));
  241. *prd = ntohs (name.sin_port);
  242. /* Nom de machine distante */
  243. machine = gethostbyaddr ((char *)&name.sin_addr,
  244. sizeof name.sin_addr, name.sin_family);
  245. if (machine == NULL) {
  246. #ifdef DEBUG
  247. perror ("Erreur de recuperation de nom de pair.\n"
  248. "gethostbyaddr() ");
  249. fprintf (stderr, "Adresse : %s (%s)\tFamille : %d (2 == AF_INET)\n",
  250. *adr, (char *)&name.sin_addr, name.sin_family);
  251. #else
  252. perror ("Impossible d'obtenir le nom d'hote distant ");
  253. #endif
  254. return;
  255. }
  256. *nom = xstrdup (machine->h_name);
  257. }