This commit is contained in:
commit
79936bfa0c
23 changed files with 1356 additions and 0 deletions
0
AUTHORS
Normal file
0
AUTHORS
Normal file
0
COPYING
Normal file
0
COPYING
Normal file
0
ChangeLog
Normal file
0
ChangeLog
Normal file
0
Doxyfile
Normal file
0
Doxyfile
Normal file
0
INSTALL
Normal file
0
INSTALL
Normal file
3
Makefile.am
Normal file
3
Makefile.am
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBDIRS = src
|
||||
|
||||
EXTRA_DIST = doc INSTALL README Doxyfile autogen.sh
|
0
NEWS
Normal file
0
NEWS
Normal file
0
README
Normal file
0
README
Normal file
11
autogen.sh
Executable file
11
autogen.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
echo "libtoolize..."
|
||||
libtoolize
|
||||
echo "aclocal..."
|
||||
aclocal
|
||||
echo "autoheader..."
|
||||
autoheader
|
||||
echo "autoconf..."
|
||||
autoconf
|
||||
echo "automake..."
|
||||
automake -a
|
||||
echo "ok."
|
61
config.h.in
Normal file
61
config.h.in
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <iostream> header file. */
|
||||
#undef HAVE_IOSTREAM
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <sstream> header file. */
|
||||
#undef HAVE_SSTREAM
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> 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
|
35
configure.in
Normal file
35
configure.in
Normal file
|
@ -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
|
||||
|
||||
|
28
src/Makefile.am
Normal file
28
src/Makefile.am
Normal file
|
@ -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../
|
||||
|
276
src/XSock.cpp
Normal file
276
src/XSock.cpp
Normal file
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
110
src/XSock.h
Normal file
110
src/XSock.h
Normal file
|
@ -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
|
102
src/XSockTCP.cpp
Normal file
102
src/XSockTCP.cpp
Normal file
|
@ -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("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
83
src/XSockUDP.cpp
Normal file
83
src/XSockUDP.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
531
src/XSockUDP_RELIABLE.cpp
Normal file
531
src/XSockUDP_RELIABLE.cpp
Normal file
|
@ -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 = "<<timer.tv_sec<<"."<< timer.tv_usec<< endl;}
|
||||
tentatives =16;
|
||||
while((tentatives > 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"<<endl;}
|
||||
break;
|
||||
}
|
||||
::sendto(this->_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 = "<<timer.tv_sec<<"."<< timer.tv_usec<< endl;}
|
||||
}
|
||||
if(tentatives==0){
|
||||
throw eConnectionClosedByPeer();
|
||||
}
|
||||
p-=SIZEADD;
|
||||
if(VERBRECV>=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 "<<sizet<<" bytes" << endl;}
|
||||
u_int *ulsbuffer = (u_int *)sbuffer, *ulrbuffer = (u_int *)rbuffer;
|
||||
u_short *ussbuffer = (u_short *)sbuffer, *usrbuffer = (u_short *)rbuffer;
|
||||
char *csbuffer = (char*)sbuffer;
|
||||
if(VERBSEND>=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;
|
||||
}
|
||||
}
|
33
src/XSock_errors.h
Normal file
33
src/XSock_errors.h
Normal file
|
@ -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
|
35
src/XSock_global.h
Normal file
35
src/XSock_global.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef _XSOCK_GLOBAL
|
||||
#define _XSOCK_GLOBAL 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* 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<Y)?Y:X
|
||||
#ifndef MIN
|
||||
#define MIN(X,Y) (X<Y)?X:Y
|
||||
#endif
|
||||
#endif
|
10
src/XSock_iface.h
Normal file
10
src/XSock_iface.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _XSOCK_INTERFACE
|
||||
#define _XSOCK_INTERFACE 1
|
||||
|
||||
/* TYPEDEFS et autre trucs non objet */
|
||||
namespace XSock {
|
||||
typedef enum {TCP,UDP_RELIABLE,UDP} protocol;
|
||||
typedef enum {SERVER,CLIENT} xsock_role;
|
||||
}
|
||||
|
||||
#endif
|
2
src/test/Makefile.am
Normal file
2
src/test/Makefile.am
Normal file
|
@ -0,0 +1,2 @@
|
|||
SUBDIRS =
|
||||
client_echo_udp server_echo_udp
|
18
src/test/client_Echo_udp/Makefile.am
Normal file
18
src/test/client_Echo_udp/Makefile.am
Normal file
|
@ -0,0 +1,18 @@
|
|||
#AM_YFLAGS = -d -v
|
||||
|
||||
SUBDIRS = .
|
||||
|
||||
bin_PROGRAMS = client_udp
|
||||
|
||||
client_udp_SOURCES = client_udp.cpp
|
||||
|
||||
client_udp_SOURCES += client_udp.h
|
||||
|
||||
INCLUDES= -I../lib/ -I./
|
||||
|
||||
client_udp_LDADD = \
|
||||
${top_builddir}/src/libXSock.la
|
||||
|
||||
client_udp_LDFLAGS = @LDFLAGS@
|
||||
|
||||
|
18
src/test/server_Echo_udp/Makefile.am
Normal file
18
src/test/server_Echo_udp/Makefile.am
Normal file
|
@ -0,0 +1,18 @@
|
|||
#AM_YFLAGS = -d -v
|
||||
|
||||
SUBDIRS = .
|
||||
|
||||
bin_PROGRAMS = server_udp
|
||||
|
||||
server_udp_SOURCES = server_udp.cpp
|
||||
|
||||
server_udp_SOURCES += server_udp.h
|
||||
|
||||
INCLUDES= -I../lib/ -I./
|
||||
|
||||
server_udp_LDADD = \
|
||||
${top_builddir}/src/libXSock.la
|
||||
|
||||
server_udp_LDFLAGS = @LDFLAGS@
|
||||
|
||||
|
Loading…
Reference in a new issue