#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; } }