commit 79936bfa0c3452f532564d12a1bcbbabc12360bc Author: glenux Date: Tue Jan 10 10:42:33 2006 +0000 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..e69de29 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..e69de29 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e1e3ed3 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +EXTRA_DIST = doc INSTALL README Doxyfile autogen.sh diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..b6037f1 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,11 @@ +echo "libtoolize..." +libtoolize +echo "aclocal..." +aclocal +echo "autoheader..." +autoheader +echo "autoconf..." +autoconf +echo "automake..." +automake -a +echo "ok." diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..453e651 --- /dev/null +++ b/config.h.in @@ -0,0 +1,61 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IOSTREAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SSTREAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..a3cf379 --- /dev/null +++ b/configure.in @@ -0,0 +1,35 @@ + +AC_INIT([xsock], [0.5], [shamox@free.fr,glenux@gmail.com]) +AC_PREREQ(2.50) + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE([xsock],[0.5]) + +AM_CONFIG_HEADER(config.h) +AC_CONFIG_SRCDIR([src/XSock.h]) +AC_PROG_INSTALL + +AC_ISC_POSIX +AC_PROG_CC + +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_CXXCPP +AC_PROG_INSTALL + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +AC_HEADER_STDC([stdio.h stdlib.h string.h unistd.h math.h time.h fcntl.h sys/stat.h sys/socket.h sys/errno.h sys/time.h sys/types.h netinet/in.h netdb.h arpa/inet.h]) + +AC_CHECK_HEADERS([iostream sstream],,AC_MSG_ERROR([You need to have the libstdc++ headers installed])) + + +AM_PROG_LIBTOOL + +AC_CONFIG_FILES([Makefile src/Makefile]) +AC_OUTPUT + + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..f589e47 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,28 @@ +SUBDIRS = . + +lib_LTLIBRARIES = libXSock.la + +#bin_PROGRAMS = libulm.o + +libXSock_la_SOURCES = \ + XSock.cpp \ + XSockTCP.cpp \ + XSockUDP.cpp \ + XSockUDP_RELIABLE.cpp + +libXSock_la_SOURCES += \ + xsock.h \ + introspect.h \ + command.h \ + macrocommand.h \ + singleton.h \ + identifiable.h + +libXSock_la_CFLAGS = -DTRACE -static + +libXSock_la_LDFLAGS = \ + -version-info 0:1:0 -no-undefined + +INCLUDES= \ + -I../ + diff --git a/src/XSock.cpp b/src/XSock.cpp new file mode 100644 index 0000000..4b4c704 --- /dev/null +++ b/src/XSock.cpp @@ -0,0 +1,276 @@ + +/*! + * \ file XSock.cpp bal bla + * + */ + +#include "XSock.h" + +/*! + * \def VERBOSE Active ou pas le mode verbeux + */ +#define VERBOSE 0 + +// constantes utilisées dans XSock.cpp et dans XSockUDP.cpp +#define NBPORTSPUB 64512 +#define PNUMPORTPUB 1025 +#define GETPORTPUB() PNUMPORTPUB+(rand()%NBPORTSPUB) + +using namespace std; +using namespace XSockExcept; + +namespace XSock { + + XSock::XSock (xsock_role role,protocol proto){ + /* initialise la structure d'addresse */ + /* on commence par vider la structure pour éviter les déchets... */ + memset(&this->_server, 0, sizeof(this->_server)); + memset(&this->_client, 0, sizeof(this->_client)); + this->_client.sin_family=AF_INET; + this->_server.sin_family=AF_INET; + + /* on initialise le systèmes de nombres aléatoires */ + srand(time(NULL)); + /* on initialise avec des addresses locales au cas où... */ + this->_client.sin_addr.s_addr=htonl(INADDR_LOOPBACK); + this->_server.sin_addr.s_addr=htonl(INADDR_LOOPBACK); + + /* et les ports au hasard */ + this->_client.sin_port=htons(0); + this->_server.sin_port=htons(0); + + /* calcule la taille de la table des descripteurs */ + this->_sockSetDSize = getdtablesize(); + + this->_role=role; + this->_proto=proto; + + this->_client_length = sizeof(this->_client); + this->_server_length = sizeof(this->_server); + + + } + + /*! + * Indique le port à utiliser sur le serveur. + */ + void XSock::port(u_short port){ + switch(this->_role){ + case CLIENT: + this->_server.sin_port=htons(port); + break; + case SERVER: + this->_server.sin_port=htons(port); + break; + default: + throw eUnknownXSockRole(); + break; + } + } + + + /*! + * Fixe la taille de la queue d'attente de connexion + */ + + void XSock::backlog(int size){ + this->_backlog=size; + } + + + /*! + * Indique l'addresse IP du serveur. + */ + + void XSock::ip(int ip){ + switch (this->_role){ + case CLIENT: + this->_server.sin_addr.s_addr=htonl(ip); + break; + case SERVER: + this->_server.sin_addr.s_addr=htonl(ip); + break; + default: + throw eUnknownXSockRole(); + break; + } + } + + void XSock::dns(string dns){ + struct hostent *he; + if ((he = gethostbyname(dns.c_str())) == NULL) { + throw eUnableToResolveName(); + } + + memcpy(&(this->_server.sin_addr.s_addr), he->h_addr_list[0], he->h_length); + + switch (this->_role){ + case CLIENT: + break; + case SERVER: + break; + default: + throw eUnknownXSockRole(); + break; + } + + } + /*! + * Connecte XSock au réseau. + */ + + void XSock::dump_info(){ + if (VERBOSE>=1){ + printf("XSock server : %d\n",this->_server.sin_addr.s_addr); + printf("XSock client : %d\n",this->_client.sin_addr.s_addr); + printf("XSock server port : %d\n",this->_server.sin_port); + printf("XSock client port : %d\n",this->_client.sin_port); + } + } + + char * XSock::getClientAddress(){ + return inet_ntoa(this->_client.sin_addr); + } + + char * XSock::getServerAddress(){ + return inet_ntoa(this->_server.sin_addr); + } + + + void XSock::launch(){ + this->dump_info(); + switch (this->_role){ + case CLIENT: + switch (this->_proto){ + case TCP: + this->launch_tcp_client(); + break; + case UDP: + this->launch_udp_client(); + break; + case UDP_RELIABLE: + this->launch_udp_reliable_client(); + break; + default: + throw eUnknownProtocol(); + break; + } + break; + case SERVER: + switch (this->_proto){ + case TCP: + this->launch_tcp_server(); + break; + case UDP: + this->launch_udp_server(); + break; + case UDP_RELIABLE: + this->launch_udp_reliable_server(); + break; + default: + throw eUnknownProtocol(); + break; + } + break; + default: + throw eUnknownXSockRole(); + break; + } + } + + /*! + * Demande a XSock de recevoir des informations. + * \param bufferData buffer de données. + * \param size taille du buffer. + */ + + ssize_t XSock::recv(void *bufferData, ssize_t size){ + switch(this->_proto){ + case TCP: + return this->recv_tcp(bufferData, size); + break; + case UDP: + return this->recv_udp(bufferData, size); + break; + case UDP_RELIABLE: + return this->recv_udp_reliable(bufferData, size); + break; + default: + throw eUnknownProtocol(); + break; + } + } + + ssize_t XSock::send(const void *bufferData, ssize_t size){ + switch(this->_proto){ + case TCP: + return this->send_tcp(bufferData, size); + break; + case UDP: + return this->send_udp(bufferData, size); + break; + case UDP_RELIABLE: + return this->send_udp_reliable(bufferData, size); + break; + default: + throw eUnknownProtocol(); + break; + } + } + + + XSock XSock::accept(){ + XSock result(CLIENT,this->_proto); + switch (this->_role){ + case CLIENT: + // TODO: râler, car le client ne recoit pas de + // connexions... + break; + case SERVER: + switch (this->_proto){ + case TCP: + result=this->accept_tcp(); + break; + case UDP: + result=this->accept_udp(); + break; + case UDP_RELIABLE: + result=this->accept_udp_reliable(); + break; + default: + throw eUnknownProtocol(); + break; + } + break; + default: + throw eUnknownXSockRole(); + break; + } + return result; + } + + void XSock::close(){ + switch (this->_proto){ + case TCP: + this->close_tcp(); + break; + case UDP: + this->close_udp(); + break; + case UDP_RELIABLE: + this->close_udp_reliable(); + break; + default: + throw eUnknownProtocol(); + break; + + } + //TODO: a faire... + } +} // end namespace + + + + + + diff --git a/src/XSock.h b/src/XSock.h new file mode 100644 index 0000000..bc88633 --- /dev/null +++ b/src/XSock.h @@ -0,0 +1,110 @@ +/*! + * \file XSock.hpp blabla + * + */ + +#ifndef _XIONFS_XSOCK +#define _XIONFS_XSOCK 1 + +#include "XSock_errors.h" +#include "XSock_global.h" +#include "XSock_iface.h" + +using namespace std; +using namespace XSockExcept; + +namespace XSock { + /* + * XSock permet de gérer une connexion TCP ou UDP. + */ + + class XSock { + private: + protocol _proto; + xsock_role _role; + + /* descripteur de la socket principale */ + int _sockFd; + + /* taille de la table des descripteurs */ + int _sockSetDSize; + + /* ensemble de sockets ouverts */ + fd_set _openSockFdSet; + + /* ensemble de sockets ouverts qui attendent d'être lus */ + fd_set _openSockFdSet_R; + + /* fixer la taille de la queue d'attente de connexions*/ + int _backlog; + + + /* membres à ajouter pour les service par dessus udp */ + // numéros de séquence entrante + u_int _secnumrecv; + // numéros de séquence sortante + u_int _secnumsend; + + /* structure d'addresse du client */ + struct sockaddr_in _client; + socklen_t _client_length; + + /* structure d'addresse du serveur */ + struct sockaddr_in _server; + socklen_t _server_length; + + void launch_tcp_client(); + void launch_udp_client(); + void launch_udp_reliable_client(); + void launch_tcp_server(); + void launch_udp_server(); + void launch_udp_reliable_server(); + + XSock accept_udp(); + XSock accept_udp_reliable(); + XSock accept_tcp(); + int sockFdTab_newPlace(); + int sockFdTab_getPlace(int); + + unsigned short XSock::getAvailablePortPub(); + + void backlog(int ); + + ssize_t send_udp(const void *, ssize_t ); + ssize_t send_udp_reliable(const void *, ssize_t ); + ssize_t send_tcp(const void *, ssize_t ); + ssize_t recv_udp(void *, ssize_t ); + ssize_t recv_udp_reliable(void *, ssize_t ); + ssize_t recv_tcp(void *, ssize_t ); + + void close_tcp(); + void close_udp(); + void close_udp_reliable(); + public: + XSock(xsock_role, protocol); + + void port(u_short ); // client + void ip(int ); + void dns(string ); + + XSock accept(); + void launch(); + void close(); + ssize_t send(const void *, ssize_t ); + ssize_t recv(void *, ssize_t ); + + char * getClientAddress(); + char * getServerAddress(); + + u_short get_local_port(); + u_short get_server_port(); + string get_server_dns(); + string get_server_ip(); + string get_client_dns(); + string get_client_ip(); + void dump_info(); + }; // end class + +} // end namespace + +#endif diff --git a/src/XSockTCP.cpp b/src/XSockTCP.cpp new file mode 100644 index 0000000..1d8129c --- /dev/null +++ b/src/XSockTCP.cpp @@ -0,0 +1,102 @@ + +#include "XSock.h" + +#define VERBOSE 0 +#define VERBOSETCP 0 + +using namespace std; +using namespace XSockExcept; + +namespace XSock { + + void XSock::close_tcp(){ + ::close(this->_sockFd); + } + + void XSock::launch_tcp_client(){ + + if((this->_sockFd=socket(AF_INET, SOCK_STREAM,0))==-1){ + perror("socket"); + throw eInvalidSocket(); + } + if (connect(this->_sockFd, + (struct sockaddr *)&this->_server, + this->_server_length) < 0) { + ::close(this->_sockFd); + perror("connect"); + throw eUnableToConnect(); + } + } + + void XSock::launch_tcp_server(){ + if((this->_sockFd=socket(AF_INET, SOCK_STREAM,0))==-1){ + throw eInvalidSocket(); + } + + if (bind(this->_sockFd, + (struct sockaddr*)&this->_server, + sizeof(this->_server))==-1) + { + throw eUnableToBind(); + } + /* + FD_ZERO(&this->_openSockFdSet); + FD_SET(this->_sockFd, &this->_openSockFdSet); + */ + if (listen(this->_sockFd,this->_backlog)==-1){ + throw eUnableToListen(); + } + } + + + XSock XSock::accept_tcp(){ + + XSock *nXSock = new XSock(CLIENT,this->_proto); + + if((nXSock->_sockFd = ::accept(this->_sockFd, + (struct sockaddr *) &nXSock->_client, + &nXSock->_client_length)) == -1){ + if(VERBOSETCP>=1){perror("accept");} + throw eUnableToAccept(); + } + + return *nXSock; + } + + ssize_t XSock::recv_tcp(void *bufferData, ssize_t size){ + //TODO: commenter + ssize_t p = read(this->_sockFd,bufferData,size); + if(p == -1) + throw XSockExcept::eSockUnreadable(); + return p; + } + + ssize_t XSock::send_tcp(const void *bufferData, ssize_t size){ + //TODO : commenter + ssize_t p = write(this->_sockFd,bufferData,size); + if(p == -1) + throw XSockExcept::eSockUnwritable(); + return p; + } + + string XSock::get_client_ip(){ + return string(inet_ntoa(this->_client.sin_addr)); + } + + string XSock::get_client_dns(){ + //TODO: tout + return string(""); + } + + string XSock::get_server_ip(){ + return string(inet_ntoa(this->_server.sin_addr)); + } + + string XSock::get_server_dns(){ + //TODO: tout + return string(""); + } + +} + + diff --git a/src/XSockUDP.cpp b/src/XSockUDP.cpp new file mode 100644 index 0000000..9c49b3d --- /dev/null +++ b/src/XSockUDP.cpp @@ -0,0 +1,83 @@ + +#include "XSock.h" + +// constantes utilisées dans XSock.cpp et dans XSockUDP.cpp +#define NBPORTSPUB 64512 +#define PNUMPORTPUB 1025 +#define GETPORTPUB() PNUMPORTPUB+(rand()%NBPORTSPUB) + +#define VERBGAPP 0 +#define VERBACCEPT 0 +#define VERBLAUNCHCLI 0 +#define VERBSEND 0 +#define VERBRECV 0 + + +#define VERBOSE 1 +#define ACK 0 +#define NON_ACK 1 +#define HI 2 +#define BYE 3 +#define SIZEADD 2*sizeof(u_short) + 2*sizeof(u_int) +#define SIZESTART 2*sizeof(u_short) + sizeof(u_int) +#define NBMAXTENTATIVES 16 +#define TIMERBASE 10000 + +using namespace std; +using namespace XSockExcept; + + +namespace XSock { + /* + extern u_int nbConn; + + void XSock::AddConnectionToManage(int desc){ + + }*/ + + void XSock::close_udp(){ + ::close(this->_sockFd); + } + + void XSock::launch_udp_client(){ + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_client\n\tentree dans launch_udp_client" << endl;} + if(this->_server.sin_port == htons(0)){ + throw eXSockNotReady(); + }else{ + // rien a faire... je crois + } + } + + void XSock::launch_udp_server(){ + /* TODO: choisir mono ou multi-processus */ + /* meme remarque que dans TCP */ + if((this->_sockFd=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP))==-1){ + perror("eInvalidSocket"); + throw eInvalidSocket(); + } + + if (bind(this->_sockFd, + (struct sockaddr*)&this->_server, + sizeof(this->_server))==-1) + { + perror("eUnableToBind"); + throw eUnableToBind(); + } + } + + XSock XSock::accept_udp(){ + // rien a faire + } + + ssize_t XSock::recv_udp(void *bufferData, ssize_t size){ + ssize_t p = read(this->_sockFd, bufferData, size); + // traiter les erreurs... + return p; + } + + ssize_t XSock::send_udp(const void *bufferData, ssize_t size){ + ssize_t p = write(this->_sockFd, bufferData, size); + // traiter les erreurs... + return p; + } +} diff --git a/src/XSockUDP_RELIABLE.cpp b/src/XSockUDP_RELIABLE.cpp new file mode 100644 index 0000000..dcc9171 --- /dev/null +++ b/src/XSockUDP_RELIABLE.cpp @@ -0,0 +1,531 @@ + +#include "XSock.h" + +// constantes utilisées dans XSock.cpp et dans XSockUDP_RELIABLE.cpp +#define NBPORTSPUB 64512 +#define PNUMPORTPUB 1025 +#define GETPORTPUB() PNUMPORTPUB+(rand()%NBPORTSPUB) + +#define VERBGAPP 0 +#define VERBACCEPT 0 +#define VERBLAUNCHCLI 0 +#define VERBSEND 0 +#define VERBRECV 0 + + +#define VERBOSE 1 +#define ACK 0 +#define NON_ACK 1 +#define HI 2 +#define BYE 3 +#define SIZEADD 2*sizeof(u_short) + 2*sizeof(u_int) +#define SIZESTART 2*sizeof(u_short) + sizeof(u_int) +#define NBMAXTENTATIVES 16 +#define TIMERBASE 10000 + +using namespace std; +using namespace XSockExcept; + +/* Fonction permettant de faire simplement un appel select avec un seul +* descripteur. +*/ +int uniselect(int desc, struct timeval timer){ + fd_set *rfdset = (fd_set *)malloc(sizeof(fd_set)); + bzero((char *)rfdset,sizeof(fd_set)); + //fd_set rfdset; + // initialisation des ensembles de descripteur + FD_ZERO(rfdset); + FD_SET(desc, rfdset); + return select(desc+1, rfdset, NULL, NULL, &timer); +} + + + +namespace XSock { + /* + extern u_int nbConn; + + void XSock::AddConnectionToManage(int desc){ + + }*/ + + void XSock::close_udp_reliable(){ + ::close(this->_sockFd); + } + + u_short XSock::getAvailablePortPub(){ + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\tdebut" << endl;} + this->_server.sin_port = htons(GETPORTPUB()); + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\t\tpremier port aleatoire obtenu : ";} + if(VERBGAPP==1){cout << this->_server.sin_port << endl;} + while((::bind(this->_sockFd, (struct sockaddr*)&this->_server, sizeof(this->_server))) == -1){ + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\t\t while bind" << endl;} + if(errno != EADDRINUSE){ + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\t\t bind err non! : " << endl;} + if(VERBOSE == 1){perror("bind");} + throw eUnableToBind(); + }else{ + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\t\t bind non!" << endl;} + this->_server.sin_port = htons(GETPORTPUB()); + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\t\t premier port aléatoire obtenu : " << ntohs(this->_server.sin_port) << endl;} + } + } + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\t\t fin while" << endl;} + if(VERBGAPP==1){cout << "--> getAvailablePortPub\n\treturn " << ntohs(this->_server.sin_port) << endl;} + return this->_server.sin_port; + } + + + void XSock::launch_udp_reliable_client(){ + /* par définition, le client est mono-processus */ + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\tentree dans launch_udp_reliable_client" << endl;} + if(this->_server.sin_port == htons(0)){ + throw eXSockNotReady(); + }else{ + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t" << endl;} + if((this->_sockFd=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP))==-1){ + throw eInvalidSocket(); + } + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\tdebut..." << endl;} + int fait = 0; + void *sbuffer = malloc(SIZESTART), *rbuffer = malloc(SIZESTART); + u_short *ussbuffer = (u_short *)sbuffer, *usrbuffer = (u_short *)rbuffer; + u_int *ulsbuffer = (u_int *)sbuffer, *ulrbuffer = (u_int *)rbuffer; + int srecv, sel, tentatives; + //struct sockaddr_in client; + struct timeval timer; + timer.tv_sec = 0; + timer.tv_usec = TIMERBASE; + //socklen_t* lenclient = (socklen_t*)malloc(sizeof(socklen_t)); + ussbuffer[0] = htons(HI); + ussbuffer[1] = 0; + this->_secnumrecv = rand(); + ulsbuffer[1] = htonl(this->_secnumrecv); + if(VERBLAUNCHCLI >=2){cout << "\t\tsec client : " << this->_secnumrecv << endl;} + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\tfin init" << endl;} + ::sendto(this->_sockFd, sbuffer, SIZESTART, 0, + (struct sockaddr*)&this->_server, sizeof(this->_server)); + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\tsendto1" << endl;} + tentatives = 0; + while(((tentatives < NBMAXTENTATIVES) && (fait <= 0)) + && (((sel = uniselect(this->_sockFd,timer)) == 0) || (sel == 1))) + { + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\twhile tentatives " << tentatives << endl;} + while((sel == 1 && (fait <= 0))){// il y a quelque chose à lire + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t while" << endl;} + srecv = ::recv(this->_sockFd, rbuffer, SIZESTART, 0); + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t recvfrom" << endl;} + if(VERBLAUNCHCLI >=2){printf("rbuffer : 0x%08x %08x\n",ulrbuffer[0],ulrbuffer[1]);} + if(srecv == SIZESTART){ // c'est pas trop petit + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t test taille oui!" << endl;} + if(HI == ntohs(usrbuffer[0])){ // c'est bien un message d'ouverture de connexion + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t test ack oui!" << endl;} + this->_secnumsend = ntohl(ulrbuffer[1]); + if(VERBLAUNCHCLI >=2){cout << "\n\t\t\tsec serveur : " << this->_secnumsend << endl;} + this->_server.sin_port = usrbuffer[1]; + if(VERBLAUNCHCLI >=2){cout << "\n\t\t\tport serveur : " << ntohs(this->_server.sin_port) << endl;} + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t recupe valeurs serveur port : " << ntohs(this->_server.sin_port) << endl;} + ::sendto(this->_sockFd, rbuffer, SIZESTART, 0, + (struct sockaddr*)&this->_server, sizeof(this->_server)); + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t sendto confirmation" << endl;} + timer.tv_usec+=timer.tv_usec/4; + if((sel = uniselect(this->_sockFd,timer)) == 0){ + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t plus qu'a sortir" << endl;} + fait = 10; + }else{ + timer.tv_usec = timer.tv_usec / 2; + } + }else{ // c'est pas un message d'ouverture de connexion, donc on jete. + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t test ack non!" << endl;} + } + }else{ // c'est trop petit, donc on jete. + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t test taille non!" << endl;} + } + sel = 0; + } + if((sel == 0) && (fait <= 0)){ + tentatives++; + ::sendto(this->_sockFd, sbuffer, SIZESTART, 0, + (struct sockaddr*)&this->_server, sizeof(this->_server)); + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\tresend1" << endl;} + }else{ + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\t fin while" << endl;} + } + } + if(tentatives >= NBMAXTENTATIVES){ + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\tfin while tentatives == " << tentatives << endl;} + throw eUnableToAccept(); + } + if(VERBLAUNCHCLI >=1){cout << "--> launch_udp_reliable_client\n\t\tfin while" << endl;} + this->_client.sin_addr.s_addr = this->_server.sin_addr.s_addr; + this->_client.sin_port = this->_server.sin_port; + } + } + + void XSock::launch_udp_reliable_server(){ + /* TODO: choisir mono ou multi-processus */ + /* même remarque que dans TCP */ + if((this->_sockFd=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP))==-1){ + perror("eInvalidSocket"); + throw eInvalidSocket(); + } + + if (bind(this->_sockFd, + (struct sockaddr*)&this->_server, + sizeof(this->_server))==-1) + { + perror("eUnableToBind"); + throw eUnableToBind(); + } + } + + XSock XSock::accept_udp_reliable(){ + //TODO: remplir + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\tdebut" << endl;} + XSock *nSock; + void *buffer = malloc(SIZESTART); + u_short *usbuffer = (u_short *)buffer; + u_int *ulbuffer = (u_int *)buffer; + int srecv; + struct sockaddr_in client; + struct timeval timer; + timer.tv_sec = 0; + timer.tv_usec = TIMERBASE; + socklen_t lenclient = sizeof(struct sockaddr_in); + + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\tfin init" << endl;} + while((srecv = ::recvfrom(this->_sockFd,buffer,SIZESTART, 0, + (struct sockaddr*)&client, &lenclient)) != 0){ + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\twhile recvfrom" << endl;} + if(srecv == -1) + throw eSockUnreadable(); + else { + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test srecv oui!" << endl;} + if(srecv == SIZESTART){ + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test taille oui!" << endl;} + u_short ack = ntohs(*usbuffer); + if(ack == HI){ + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test ack oui!" << endl;} + //initialisation du nouveau XSock + nSock = new XSock(CLIENT,this->_proto); + nSock->_secnumsend = ntohl(ulbuffer[1]); + if(VERBACCEPT >=2){cout << "\n\t\t\tsec client = " << nSock->_secnumsend << endl;} + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t new sock cree" << endl;} + if((nSock->_sockFd = ::socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP)) == -1){ + throw eInvalidSocket(); + } + if(VERBACCEPT <= -1){cout << "--> accept_udp_reliable\n\t nSock->_sockFd : " << nSock->_sockFd << endl;} + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test socket ok!" << endl;} + nSock->_client.sin_addr.s_addr = client.sin_addr.s_addr; + if(VERBACCEPT >=2){cout << "\n\t\t\tadresse client : " << inet_ntoa(nSock->_client.sin_addr) << endl;} + nSock->_client.sin_port = client.sin_port; + if(VERBACCEPT >=2){cout << "\n\t\t\tport client : " << ntohs(nSock->_client.sin_port) << endl;} + u_short port = nSock->getAvailablePortPub(); + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t new port ok!" << endl;} + + // prépare message avec port + numseqence + ulbuffer[0] = htonl(HI*0x10000+port); + nSock->_secnumrecv = rand(); + ulbuffer[1] = htonl(nSock->_secnumrecv); + //(u_short)buffer[sizeof(u_short) + sizeof(u_int)] = (u_short)htons(port); + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t init buffer\n\t\t\tack = " << *(u_short*)buffer;} + if(VERBACCEPT >=2){cout << "\n\t\t\tsecnum serveur = " << nSock->_secnumrecv;} + if(VERBACCEPT >=2){cout << "\n\t\t\tport serveur = " << port << endl;} + if(VERBACCEPT >=2){printf("message envoye : 0x%08x %08x ==\t ack|port : 0x%08x sec : 0x%08x\n", + ulbuffer[0],ulbuffer[1], + htonl(HI*0x10000+port), + htonl(nSock->_secnumrecv));} + + // envoie du message et attente de confirmation. + ::sendto(nSock->_sockFd, buffer, SIZESTART, 0, + (struct sockaddr*)&nSock->_client, nSock->_client_length); + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t sendto" << endl;} + void *rbuffer = malloc(SIZESTART); + u_short *usrbuffer = (u_short *)rbuffer; + u_int *ulrbuffer = (u_int *)rbuffer; + int sel,tentatives = 0; + struct sockaddr_in client2; + while((tentatives < NBMAXTENTATIVES) + && (((sel = uniselect(nSock->_sockFd,timer)) == 0) || (sel == 1))) + { + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t while tentative " << tentatives << endl;} + if(sel == 1){ + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test sel oui!" << endl;} + lenclient = sizeof(client2); + srecv = ::recvfrom(nSock->_sockFd, rbuffer, SIZESTART, 0, + (struct sockaddr*)&client2, &lenclient); + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t recvfrom" << endl;} + if((client2.sin_addr.s_addr == nSock->_client.sin_addr.s_addr) + && (client2.sin_port == nSock->_client.sin_port)) + { + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test bon client oui!" << endl;} + if((usrbuffer[0] == htons(HI)) && + (usrbuffer[1] == usbuffer[1]) && + (ulrbuffer[1] == ulbuffer[1])) + { + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test ack oui!" << endl;} + break; + } + } + }else{ + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t test sel non!" << endl;} + ::sendto(nSock->_sockFd, buffer, SIZESTART, 0, + (struct sockaddr*)&nSock->_client, nSock->_client_length); + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t sendto" << endl;} + } + tentatives++; + } + if(tentatives == NBMAXTENTATIVES){ + break; + } + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t fin while\n\t\tretour ok!" << endl;} + // on attend car en face il attend voir si on renvoie pas un message... + usleep(timer.tv_usec*2); + return *nSock;// à remplacer plus tard en renvoyant le pointeur direct + } + } + } + } + if(VERBACCEPT >=1){cout << "--> accept_udp_reliable\n\t\t probleme!!" << endl;} + throw eUnableToAccept(); + } + + ssize_t XSock::recv_udp_reliable(void *bufferData, ssize_t size){ + //TODO : le ACK est fait avec une fentre de 1 + // il y a plein de problèmes générés par ce système très incomplet. + // mettre un système de timer évolutif + u_int tentatives =16; + if(VERBRECV==1){cout << "--> recv_udp_reliable\n\tdebut" << endl;} + ssize_t p = 0; + struct timeval timer; + char *cbufferData = (char*)bufferData; + timer.tv_sec = 0; + timer.tv_usec = TIMERBASE; + ssize_t sizet = SIZEADD + size; + void *rbuffer = malloc(sizet), *sbuffer = malloc(SIZEADD); + u_int *ulrbuffer = (u_int *)rbuffer, *ulsbuffer = (u_int *)sbuffer; + u_short *usrbuffer = (u_short *)rbuffer, *ussbuffer = (u_short *)sbuffer; + char *crbuffer = (char*)rbuffer; + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\tfin init" << endl;} + if(VERBRECV>=2){ + cout << "--> recv_udp_reliable\n\t this->_sockFd = " << this->_sockFd << endl; + } + if((p = ::recv(this->_sockFd,rbuffer,sizet,0)) == -1){ + if(VERBRECV>=1){perror("XSock::recv{recv}");} + throw eSockUnreadable(); + } + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t\trecv ok! p = " << p << endl;} + p-=SIZEADD; + if(VERBRECV>=2){cout << "--> recv_udp_reliable\n\t\t p-SIZEADD = " << p << endl;} + int renv = 0, recevoir = 0, env = 0; + tentatives = 16; + while((tentatives > 0) && (p >= 0)){ + tentatives--; + switch (usrbuffer[0]){ + case ACK : + { + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t ack == ack alors qu'on est dans le recv" << endl;} + + recevoir = 10; + break; + } + case NON_ACK : + { + if((this->_secnumrecv > ntohl(ulrbuffer[1])) || (this->_secnumrecv < ntohl(ulrbuffer[1]))){ + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t secnum >< recu" << endl;} + ussbuffer[0] = htons(ACK); + ulsbuffer[1] = htonl(this->_secnumrecv); + renv = 10; + recevoir = 10; + }else{ + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t secnum == recu (= " << this->_secnumrecv << ")" << endl;} + ussbuffer[0] = htons(ACK); + this->_secnumrecv+=p; + ulsbuffer[1] = htonl(this->_secnumrecv); + if(VERBRECV>=2){cout << "--> recv_udp_reliable\n\t nouv secnum = " << this->_secnumrecv << endl;} + env = 10; + } + break; + } + case BYE : + {//fermeture de la connexion + ::sendto(this->_sockFd, rbuffer, SIZEADD, 0, (struct sockaddr*)&this->_client, this->_client_length); + while((uniselect(this->_sockFd,timer)) == 1){ + ::sendto(this->_sockFd, rbuffer, SIZEADD, 0, (struct sockaddr*)&this->_client, this->_client_length); + } + throw eConnectionClosedByPeer(); + break; + } + default : + { + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t ack inconnu ou HI en pleine connection..." << endl;} + throw eSockUnreadable(); + } + } + if(renv == 10){ + ::sendto(this->_sockFd, sbuffer, SIZEADD, 0, (struct sockaddr*)&this->_client, this->_client_length); + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t resend data" << endl;} + } + if(recevoir == 10){ + if((p = ::recv(this->_sockFd,rbuffer,sizet,0)) == -1){ + if(VERBRECV>=1){perror("XSock::recv{recv}");} + throw eSockUnreadable(); + } + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t\t recv ok! p = " << p << endl;} + p-=SIZEADD; + } + if(env == 10){ + ::sendto(this->_sockFd, sbuffer, SIZEADD, 0, (struct sockaddr*)&this->_client, this->_client_length); + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t send ack" << endl;} + break; + } + } + if(tentatives==0){ + throw eConnectionClosedByPeer(); + } + //recopie des données + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\trempli bufferData" << endl;} + for(int i = 0;((i < p) || (i < size)); i++){ + cbufferData[i] = crbuffer[i+SIZEADD]; + if(VERBRECV>=3){printf("%02x -> %02x\n", crbuffer[i+SIZEADD], cbufferData[i]);} + } + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\t fin while" << endl;} + timer.tv_usec+=timer.tv_usec/2; + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\ttimer = "< 0) && ((uniselect(this->_sockFd, timer)) == 1)){ + tentatives--; + if((p = ::recv(this->_sockFd,rbuffer,sizet,0)) == -1){ + if(VERBRECV>=1){perror("XSock::recv{recv}");} + throw eSockUnreadable(); + } + if(ulrbuffer[1] == this->_secnumrecv){ + if(VERBRECV>=1){cout <<"--> recv_udp_reliable\n\t recu nouvelles donnees avec bon ack recv. on sort"<_sockFd, sbuffer, SIZEADD, 0, (struct sockaddr*)&this->_client, this->_client_length); + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\tresend ack" << endl;} + if(VERBRECV>=1){cout << "--> recv_udp_reliable\n\ttimer = "<=1){cout << "--> recv_udp_reliable\n\treturning..." << endl;} + //usleep(timer.tv_usec); + return p; + } + + ssize_t XSock::send_udp_reliable(const void *bufferData, ssize_t size){ + //TODO : mettre un système de timer évolutif + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\tdebut" << endl;} + struct timeval timer; + u_int tentatives = 16; + char *cbufferData = (char *)bufferData; + timer.tv_sec = 0; + timer.tv_usec = TIMERBASE; + int sel; + //--- + ssize_t p = 0, sizet = size+SIZEADD, srecv; + void *sbuffer = malloc(sizet), *rbuffer = malloc(SIZEADD); + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\tpreparing buffer of "<=1){cout << "--> send_udp_reliable\n\tfin init" << endl;} + for(int i = 0; i < size; i++){ + csbuffer[i+SIZEADD] = cbufferData[i]; + } + ussbuffer[0] = htons(NON_ACK); + ulsbuffer[1] = htonl(this->_secnumsend); + ulsbuffer[2] = htonl(this->_secnumrecv); + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\tfin prepare sbuffer with secnum = " << this->_secnumsend << endl;} + if(VERBSEND>=2){cout << "size of data to send : " << size << endl;} + if(VERBSEND>=3){ + cout << "data to send :" << endl; + for(int i = 0; i < sizet;i++){ + printf("%02x ", (char)csbuffer[i]); + } + } + srecv=0; + p = ::sendto(this->_sockFd, sbuffer, sizet, 0, (struct sockaddr*)&this->_client, this->_client_length); + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\tsend" << endl;} + if(VERBSEND>=2){cout << "size of data sent : " << (p-SIZEADD) << endl;} + tentatives = 16; + while((tentatives > 0) && (sel = uniselect(this->_sockFd,timer)) == 0){ + tentatives--; + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t resend data" << endl;} + p = ::sendto(this->_sockFd, sbuffer, sizet, 0, (struct sockaddr*)&this->_client, this->_client_length); + } + if(tentatives==0){ + throw eConnectionClosedByPeer(); + } + p-=SIZEADD; + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t fin while" << endl;} + if(sel == -1){ + if(VERBSEND>=1){perror("XSock::send_udp_reliable{sel}");} + throw eSockUnreadable(); + } + if((srecv = ::recv(this->_sockFd, rbuffer, SIZEADD,0)) == -1){ + if(VERBSEND>=1){perror("XSock::send_udp_reliable{recv}");} + throw eSockUnreadable(); + } + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\trecv ok!" << endl;} + if(VERBSEND>=2){cout << "--> send_udp_reliable\n\t size = " << srecv << endl;} + if(VERBSEND>=2){cout << "--> send_udp_reliable\n\t ack = " << ntohs(usrbuffer[0]) << endl;} + if(VERBSEND>=2){cout << "--> send_udp_reliable\n\t sec = " << ntohl(ulrbuffer[1]) << endl;} + u_int secawaited = this->_secnumsend + p; + if(VERBSEND>=2){cout << "--> send_udp_reliable\n\t sec awaited = " << secawaited << endl;} + tentatives = 16; + while((tentatives > 0) && ((srecv != SIZEADD) || (ntohs(usrbuffer[0]) != ACK) || (secawaited != ntohl(ulrbuffer[1])))) + { + tentatives--; + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t while" << endl;} + if(srecv == SIZEADD){ + if(ntohs(usrbuffer[0]) == NON_ACK){ + // on remarque que si le message envoyé continet le ack du message précédent + // ie this->_secnumsend == ulrbuffer[2] alors c'est comme un acquittement + // on drop tout de meme le paquet. + //if(secawaited == ulrbuffer[2]){ + // if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t acked with send action" << endl;} + // this->_secnumsend =secawaited; + // return p; + //} + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t dead lock" << endl;} + throw eDeadLock(); + } + } + p = ::sendto(this->_sockFd, sbuffer, sizet, 0, (struct sockaddr*)&this->_client, this->_client_length); + while((sel = uniselect(this->_sockFd,timer)) == 0){ + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t resend data" << endl;} + p = ::sendto(this->_sockFd, sbuffer, sizet, 0, (struct sockaddr*)&this->_client, this->_client_length); + } + p-=SIZEADD; + if((srecv = ::recv(this->_sockFd, rbuffer, SIZEADD,0)) == -1){ + if(VERBSEND>=1){perror("XSock::send_udp_reliable{recv}");} + throw eSockUnreadable(); + } + } + if(tentatives==0){ + throw eConnectionClosedByPeer(); + } + if(srecv == SIZEADD){ + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t verif taille ok!" << endl;} + if(ntohs(usrbuffer[0]) == ACK){// on est content + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t verif ACK ok!" << endl;} + if(this->_secnumsend + p == ntohl(ulrbuffer[1])){ + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t verif secnum ok! returning..." << endl;} + //c'est bon ! + usleep(timer.tv_usec); + this->_secnumsend+=p; + return p; + } + } + } + //impossible d'arriver ici normalement + if(VERBSEND>=1){cout << "--> send_udp_reliable\n\t soucis!!!" << endl;} + + + return p; + } +} diff --git a/src/XSock_errors.h b/src/XSock_errors.h new file mode 100644 index 0000000..c20881f --- /dev/null +++ b/src/XSock_errors.h @@ -0,0 +1,33 @@ +#ifndef _XSOCK_ERRORS +#define _XSOCK_ERRORS 1 + +namespace XSockExcept { + class eXSockExcept { }; + class eInvalidSocket : eXSockExcept { }; + class eUnknownProtocol : eXSockExcept { }; + class eUnableToListen : eXSockExcept { }; + class eUnableToConnect : eXSockExcept { }; + class eUnableToAccept : eXSockExcept { }; + class eUnableToBind : eXSockExcept { }; + class eSockUnreadable : eXSockExcept { }; + class eSockUnwritable : eXSockExcept { }; + class eUnknownXSockRole : eXSockExcept { }; + class eUnableToResolveName : eXSockExcept { }; + class eXSockNotReady : eXSockExcept { }; + class eConnectionClosedByPeer : eXSockExcept { }; + class eDeadLock : eXSockExcept { }; + class eUnableToLock : eXSockExcept { }; + class eUnableToUnlock : eXSockExcept { }; + class eUnableToCloseFile : eXSockExcept { }; + class eUnableToOpenFile : eXSockExcept { }; + class eUnableToStatFile : eXSockExcept { }; + class eUnableToOpen2ndFile : eXSockExcept { }; + class eUnableToCreateFile : eXSockExcept { }; + class eUnableToDeleteFile : eXSockExcept { }; + class eUnableToReadFile : eXSockExcept { }; + class eUnableToWriteFile : eXSockExcept { }; + /* définition des exceptions ici */ + +} + +#endif diff --git a/src/XSock_global.h b/src/XSock_global.h new file mode 100644 index 0000000..0e2ed6e --- /dev/null +++ b/src/XSock_global.h @@ -0,0 +1,35 @@ +#ifndef _XSOCK_GLOBAL +#define _XSOCK_GLOBAL 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* spécifie le nombre maximum de demandes de connexion en attente d'être acceptées. */ + +#define XSOCK_MESSAGES_LENGTH 128 +#define XSOCK_CHUNK_LENGTH 4096 +#define XSOCK_INVALID_SOCKET -1 +#define MAXGAUCHE(X,Y) (X