summaryrefslogtreecommitdiff
path: root/jeu-test/tetris_lan_src/tcpip.c
diff options
context:
space:
mode:
Diffstat (limited to 'jeu-test/tetris_lan_src/tcpip.c')
-rw-r--r--jeu-test/tetris_lan_src/tcpip.c541
1 files changed, 541 insertions, 0 deletions
diff --git a/jeu-test/tetris_lan_src/tcpip.c b/jeu-test/tetris_lan_src/tcpip.c
new file mode 100644
index 0000000..5afcbdf
--- /dev/null
+++ b/jeu-test/tetris_lan_src/tcpip.c
@@ -0,0 +1,541 @@
+
+#include "includes.h"
+
+#ifdef WIN32
+#define socklen_t int
+
+#include "Winsock2.h"
+#endif
+
+#ifdef __LINUX__
+typedef enum { FALSE=0, TRUE } BOOL;
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netinet/tcp.h> // Pour TCP_NODELAY et SOL_TCP.
+
+#include <errno.h>
+#endif
+
+struct SSock
+{
+ BOOL nCnx; // Socket connectée ou pas.
+ int nSocket; // No de socket.
+ struct in_addr nIPAddr; // IP du client connecté.
+};
+struct SSock gSockListen; // Socket d'écoute du Master.
+struct SSock gSockCom; // Mst: Socket de com avec le client / Clt: Socket de com avec le master.
+
+struct STCPIP
+{
+#ifdef WIN32
+ WSADATA WSAData;
+#endif
+
+};
+struct STCPIP gTCPIP;
+
+//=============================================================================
+//=============================================================================
+
+// Init.
+void TCP_EngineInit(void)
+{
+#ifdef WIN32
+ int nRet;
+ nRet = WSAStartup(MAKEWORD(2,2), &gTCPIP.WSAData);
+ if (nRet != 0)
+ {
+ printf("Unable to initialize Winsock: %d %d", nRet, WSAGetLastError());
+ exit (1);
+ }
+#endif
+
+ gVar.nTCPMaster = 0; // 1 = Master / 0 = Slave.
+
+}
+
+// Fermeture.
+void TCP_EngineClose(void)
+{
+#ifdef WIN32
+ WSACleanup();
+#endif
+}
+
+#ifdef WIN32
+// Passage socket en mode bloquant / non bloquant.
+// Out : 0 = Ok.
+int Sock_SetBlockMode(int nSocket, BOOL bBlock)
+{
+ int errsv;
+ int nResult;
+ u32 arg = (bBlock == TRUE ? 0 : 1);
+
+ if ((nResult = ioctlsocket(nSocket, FIONBIO, &arg)) == SOCKET_ERROR)
+ {
+ errsv = WSAGetLastError();
+ printf("ioctlsocket: Error (%d).\n", errsv);
+ exit (1);
+ }
+
+ return (nResult);
+}
+#endif
+
+#ifdef __LINUX__
+// Passage socket en mode bloquant / non bloquant.
+int Sock_SetBlockMode(int nSocket, BOOL nBlock)
+{
+ int flags;
+ int r;
+ int errsv;
+
+ if ((flags = fcntl(nSocket, F_GETFL)) == -1)
+ {
+ errsv = errno;
+ printf("fnctl1: %d - %s\n", errsv, strerror(errsv));
+ exit (1);
+ }
+
+ if (nBlock == TRUE)
+ {
+ r = fcntl(nSocket, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ else
+ {
+ r = fcntl(nSocket, F_SETFL, flags | O_NONBLOCK);
+ }
+ if (r == -1)
+ {
+ errsv = errno;
+ printf("fnctl2: %d - %s\n", errsv, strerror(errsv));
+ exit (1);
+ }
+
+ return (r);
+}
+#endif
+
+// Place le flag TCP_NODELAY pour couper le "Nagle algorithm".
+// Out : 0 = Ok / 1 = Erreur.
+int Sock_SetTcpNoDelay(int nSocket, BOOL bVal)
+{
+ int errsv;
+#ifdef WIN32
+ BOOL bOptVal = bVal;
+ int bOptLen = sizeof(BOOL);
+
+ if (setsockopt(nSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&bOptVal, bOptLen) == SOCKET_ERROR)
+ {
+ errsv = WSAGetLastError();
+ printf("setsockopt: Error (%d).\n", errsv);
+ return (1);
+ }
+#endif
+#ifdef __LINUX__
+ int nOnOff = (bVal == TRUE ? 1 : 0);
+
+ if (setsockopt(nSocket, SOL_TCP, TCP_NODELAY, &nOnOff, sizeof(nOnOff)) == -1)
+ {
+ errsv = errno;
+ printf("setsockopt: %d - %s\n", errsv, strerror(errsv));
+ return (1);
+ }
+#endif
+
+ printf("TCP_NODELAY: Ok.\n");
+
+ return (0);
+}
+
+// Ouverture de socket.
+int SocketOpen(void)
+{
+ int nSocket;
+#ifdef WIN32
+ //if ((nSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
+ if ((nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
+ {
+ printf("SocketOpen(): Unable to open socket.\n");
+ exit (1);
+ }
+
+ // Flag SO_REUSEADDR : Normalement, ne sert que du côté serveur. Au cas où il y ait un crash et que la socket n'ait pas été correctement fermée.
+ BOOL bOptVal = TRUE;
+ int bOptLen = sizeof(BOOL);
+ if (setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen) == SOCKET_ERROR)
+ {
+ int errsv = WSAGetLastError();
+ printf("setsockopt: Error (%d).\n", errsv);
+ }
+ else
+ {
+ printf("SO_REUSEADDR: Ok.\n");
+ }
+#endif
+#ifdef __LINUX__
+ //if ((nSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ if ((nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ {
+ int errsv;
+ errsv = errno;
+ printf("SocketOpen(): %d - %s\n", errsv, strerror(errsv));
+ exit (1);
+ }
+
+ // Flag SO_REUSEADDR : Normalement, ne sert que du côté serveur. Au cas où il y ait un crash et que la socket n'ait pas été correctement fermée.
+ int on = 1;
+ if (setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
+ {
+ int errsv = errno;
+ printf("setsockopt: %d - %s\n", errsv, strerror(errsv));
+ }
+ else
+ {
+ printf("SO_REUSEADDR: Ok.\n");
+ }
+#endif
+ return (nSocket);
+}
+
+// Fermeture de socket.
+void SocketClose(int nSocket)
+{
+ int errsv;
+
+#ifdef WIN32
+ if (closesocket(nSocket) == SOCKET_ERROR)
+ {
+ errsv = WSAGetLastError();
+ printf("SocketClose: Error while closing socket (%d).\n", errsv);
+ exit (1);
+ }
+#endif
+#ifdef __LINUX__
+ if (close(nSocket) == -1)
+ {
+ errsv = errno;
+ printf("SocketClose: %d - %s\n", errsv, strerror(errsv));
+ exit (1);
+ }
+#endif
+}
+
+//=============================================================================
+//=============================================================================
+
+// Server:
+// socket / bind / listen / accept / send and-or recv / close
+
+// Start.
+void TCPServerStart(void)
+{
+ int errsv;
+
+ // Ouverture d'une socket pour l'écoute.
+ gSockListen.nSocket = SocketOpen();
+ // Passage de la socket en mode non bloquant...
+ Sock_SetBlockMode(gSockListen.nSocket, FALSE);
+ Sock_SetTcpNoDelay(gSockListen.nSocket, TRUE); // ...et en TCP_NODELAY.
+ // bind.
+ struct sockaddr_in sSrv;
+ memset(&sSrv, 0, sizeof(sSrv));
+ sSrv.sin_family = AF_INET;
+ sSrv.sin_addr.s_addr = htonl(INADDR_ANY); // Ecoute sur toutes les adresses IP LOCALES.
+ sSrv.sin_port = htons(gVar.nPort);
+ if (bind(gSockListen.nSocket, (struct sockaddr *)&sSrv, sizeof(sSrv)) != 0)
+ {
+#ifdef WIN32
+ errsv = WSAGetLastError();
+ printf("bind: Failed (%d).\n", errsv);
+#endif
+#ifdef __LINUX__
+ errsv = errno;
+ printf("bind: tcpip l.258 %d - %s\n", errsv, strerror(errsv));
+#endif
+ exit (1);
+ }
+ // listen.
+ if (listen(gSockListen.nSocket, 1) != 0)
+ {
+#ifdef WIN32
+ errsv = WSAGetLastError();
+ printf("listen: Failed (%d).\n", errsv);
+#endif
+#ifdef __LINUX__
+ errsv = errno;
+ printf("listen: %d - %s\n", errsv, strerror(errsv));
+#endif
+ exit (1);
+ }
+ gSockListen.nCnx = TRUE;
+
+ printf("Server started.\n\n");
+
+ // Reset du slot de connexion client.
+ gSockCom.nCnx = FALSE;
+
+}
+
+// A placer dans une boucle, attend la connexion des clients.
+u32 TCPServer_WaitForClient(void)
+{
+ struct sockaddr_in sFrom;
+ socklen_t nFromLen = sizeof(sFrom);
+ int errsv;
+
+ // accept.
+ int nAccept;
+ memset(&sFrom, 0, sizeof(sFrom));
+#ifdef WIN32
+ if ((nAccept = accept(gSockListen.nSocket, (struct sockaddr *)&sFrom, &nFromLen)) == -1)
+ {
+ errsv = WSAGetLastError();
+ if (errsv != WSAEWOULDBLOCK)
+ {
+ printf("accept: Error (%d).\n", errsv);
+ exit (1);
+ }
+ }
+#endif
+#ifdef __LINUX__
+ if ((nAccept = accept(gSockListen.nSocket, (struct sockaddr *)&sFrom, &nFromLen)) == -1)
+ {
+ errsv = errno;
+ if (errsv != EWOULDBLOCK)
+ {
+ printf("accept: %d - %s\n", errsv, strerror(errsv));
+ exit (1);
+ }
+ }
+#endif
+ else
+ {
+ // Une connexion a eu lieu.
+ printf("Incoming connexion from IP: %s\n", inet_ntoa(sFrom.sin_addr));
+ //
+ gSockCom.nSocket = nAccept;
+ gSockCom.nIPAddr = sFrom.sin_addr;
+ Sock_SetBlockMode(gSockCom.nSocket, FALSE); // On passe la socket client en mode non bloquant...
+ Sock_SetTcpNoDelay(gSockCom.nSocket, TRUE); // ...et en TCP_NODELAY.
+ gSockCom.nCnx = TRUE;
+ printf("Client connected.\n");
+ return (1);
+ }
+
+ return (0);
+
+}
+
+// Stop.
+void TCPServerStop(void)
+{
+ // Fermeture des sockets :
+ // Socket d'écoute.
+ if (gSockListen.nCnx == TRUE) SocketClose(gSockListen.nSocket);
+ // Socket Client.
+ if (gSockCom.nCnx == TRUE) SocketClose(gSockCom.nSocket);
+
+}
+
+//=============================================================================
+//=============================================================================
+
+// Client:
+// socket / connect / send and-or recv / close
+
+// Start.
+void TCPClientStart(void)
+{
+ // Ouverture de socket.
+ gSockCom.nSocket = SocketOpen();
+ // On passe la socket en mode non bloquant...
+ Sock_SetBlockMode(gSockCom.nSocket, FALSE);
+ Sock_SetTcpNoDelay(gSockCom.nSocket, TRUE); // ...et en TCP_NODELAY.
+ //
+ gSockCom.nCnx = TRUE;
+
+}
+
+// A placer dans une boucle, se connecte au serveur et attend la connexion.
+u32 TCPClient_ConnectToServer(void)
+{
+ // connect.
+ int errsv;
+ struct sockaddr_in sDst;
+ memset(&sDst, 0, sizeof(sDst));
+ sDst.sin_family = AF_INET;
+ sDst.sin_addr.s_addr = inet_addr(gVar.pIPAddress); //inet_addr(gPrm.pIPAddr);
+ sDst.sin_port = htons(gVar.nPort);
+
+#ifdef WIN32
+ if (connect(gSockCom.nSocket, (struct sockaddr *)&sDst, sizeof(sDst)) != 0)
+ {
+ errsv = WSAGetLastError();
+//printf("connect: %d\n", errsv);
+//WSAEWOULDBLOCK : 10035
+//WSAEALREADY : 10037
+//WSAEISCONN : 10056
+//WSAENOTCONN : 10057
+ if (errsv == WSAEISCONN)
+ {
+printf("connect: Success!\n\n");
+ return (1);
+ }
+ }
+#endif
+#ifdef __LINUX__
+ if (connect(gSockCom.nSocket, (struct sockaddr *)&sDst, sizeof(sDst)) != 0)
+ {
+ errsv = errno;
+//printf("connect: %d - %s\n", errsv, strerror(errsv));
+ if (errsv == EISCONN)
+ {
+printf("connect: Success!\n\n");
+ return (1);
+ }
+ }
+#endif
+
+ return (0);
+}
+
+// Stop.
+void TCPClientStop(void)
+{
+ // Fermeture de la socket.
+ if (gSockCom.nCnx == TRUE) SocketClose(gSockCom.nSocket);
+
+}
+
+//=============================================================================
+//=============================================================================
+
+// Réception d'un message.
+// Le ou les messages sont copiés dans pRcvBuf (taille du buffer nRcvBufSzMax) et le nombre de bytes reçus renvoyé via pRcvBufSz.
+u32 TCPReceive(int nSocket, u8 *pRcvBuf, u32 nRcvBufSzMax, u32 *pRcvBufSz)
+{
+ int nRecv;
+ int errsv;
+
+ // recv.
+ memset(pRcvBuf, 0, nRcvBufSzMax);
+#ifdef WIN32
+ if ((nRecv = recv(nSocket, pRcvBuf, nRcvBufSzMax, 0)) == SOCKET_ERROR)
+ {
+ errsv = WSAGetLastError();
+ if (errsv != WSAEWOULDBLOCK)
+ {
+ printf("recv: Error (%d).\n", errsv);
+ //exit (1);
+ }
+ }
+#endif
+#ifdef __LINUX__
+ if ((nRecv = recv(nSocket, pRcvBuf, nRcvBufSzMax, 0)) == -1)
+ {
+ errsv = errno;
+ if (errsv != EAGAIN)
+ {
+ printf("recv: %d - %s\n", errsv, strerror(errsv));
+ //exit (1);
+ }
+ }
+#endif
+ else
+ {
+ // Message reçu.
+ *pRcvBufSz = nRecv;
+
+printf("recv: %d bytes\n", nRecv);
+
+if (nRecv == 0) exit(1); // à revoir... Pour éviter la fin.
+
+ return (1);
+ }
+
+ return (0);
+}
+
+// Appelable depuis l'extérieur (sans s'occuper des sockets).
+// Renvoie : 0 = Rien n'a été reçu / 1 = Un(des) message(s) reçu(s) + taille en bytes dans pSz.
+u32 TCP_Receive(u8 *pBuf, u32 nSz, u32 *pSz)
+{
+ return (TCPReceive(gSockCom.nSocket, pBuf, nSz, pSz));
+}
+
+
+// Envoi d'un message.
+void TCPSend(int nSocket, u8 *pBuf, u32 nSz)
+{
+ int errsv;
+ int nSend;
+
+#ifdef WIN32
+ if ((nSend = send(nSocket, (char *)pBuf, nSz, 0)) == SOCKET_ERROR)
+ {
+ errsv = WSAGetLastError();
+ printf("send: Error (%d).\n", errsv);
+ //exit (1);
+ }
+#endif
+#ifdef __LINUX__
+ if ((nSend = send(nSocket, (char *)pBuf, nSz, 0)) == -1)
+ {
+ errsv = errno;
+ printf("send: %d - %s\n", errsv, strerror(errsv));
+ //exit (1);
+ }
+#endif
+
+}
+
+// Envoi d'un message.
+// Appelable depuis l'extérieur (sans s'occuper des sockets).
+void TCP_Send(u8 *pBuf, u32 nSz)
+{
+ TCPSend(gSockCom.nSocket, pBuf, nSz);
+}
+
+//=============================================================================
+//=============================================================================
+
+// Ouverture de la cnx.
+void TCP_CnxOpen(void)
+{
+ if (gVar.nTCPMaster)
+ {
+ TCPServerStart();
+ }
+ else
+ {
+ TCPClientStart();
+ }
+}
+
+// Attente de la cnx. A placer dans une boucle.
+u32 TCP_CnxWait(void)
+{
+ return (gVar.nTCPMaster ? TCPServer_WaitForClient() : TCPClient_ConnectToServer());
+}
+
+// Fermeture de la cnx.
+void TCP_CnxClose(void)
+{
+ if (gVar.nTCPMaster)
+ {
+ TCPServerStop();
+ }
+ else
+ {
+ TCPClientStop();
+ }
+printf("TCP_CnxClose() : Ok.\n");
+}
+
+
+