Proxy irc simple (windows/winsock)

Soyez le premier à donner votre avis sur cette source.

Snippet vu 5 600 fois - Téléchargée 21 fois

Contenu du snippet

Proxy IRC, permettant de créer un log des communications entre le client et le serveur.

La connexion avec le serveur est initialisée dès qu'un client se connecte. Dès lors, tous les échanges sont redirigés sur la sortie standard.

Les logs se visualisent difficilement avec WordPad mais assez bien avec Bloc Note. Si cela vous gène, n'hésitez pas à envoyer un mail à Microsoft pour leur expliquer à quel point leur crlf fait chier tout le monde.

Compilé avec Microsoft Visual Studio 2008 - Professional Edition.
Options de compilation par défaut d'un projet Win32 console vide sauf :
- Character Set : No Set
- C/C++ -> Warning Level : Level 4
Désolé pour les aficionados d'autres compilateurs, il faudra peut-être quelques adaptations. Mais si vous êtes étudiant, sachez que Visual Studio est offert. (moi, je fais de la pub? nooon...)

Testé avec mIRC et telnet comme clients, irc.worldnet.net comme serveur.

Source / Exemple :


/*
    RelaisIRC - Relais entre un client IRC et un serveur IRC pour obtenir un log.
    Port du relais : 6667

    Dernière modification le 11/07/2009 19h30

  • /
#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") #define T_FROM_SERVER 0 // Message reçu de la partie serveur #define T_FROM_CLIENT 1 // Message reçu de la partie cliente #define T_CLIENT_END 2 // Fin de connexion de la partie cliente #define T_SERVER_END 3 // Fin de la connexion de la partie serveur typedef struct __MESSAGE { int Type; // T_***, cf. plus haut char *Contenu; // Contenu du message, terminée par '\0' int TailleMessage; // Taille du message sans le '\0' final, pour T_FROM_SERVER et T_FROM_CLIENT struct __MESSAGE *Suivant; } MESSAGE; SOCKET ClientSocket, ServerSocket; CRITICAL_SECTION AccesPile; MESSAGE *Pile; // Pile de messages HANDLE EtatPile; // Event, permet l'attente de la thread de travail quand la pile est vide BOOL EtatThreadClient, EtatThreadServeur; DWORD WINAPI ThreadClient (LPVOID lpParameter); DWORD WINAPI ThreadServeur (LPVOID lpParameter); int main(int argc, char **argv) { WSADATA wsaData; int iResult; struct addrinfo *result, hints; SOCKET ListenSocket; MESSAGE *MessageTmp; // Attend deux paramètres : l'adresse du serveur et le numéro du port. if (argc != 3) { printf ("Erreur - Nombre de parametres incorrect.\n"); printf ("Exemple de syntaxe correcte :`\"Relais irc.worldnet.net 6667\"\n"); printf ("\n"); return -1; } iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return -1; } // Crée d'abord la partie serveur ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; iResult = getaddrinfo(NULL, "6667", &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %d\n", iResult); WSACleanup(); return -1; } ListenSocket = socket (result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { printf("Error at socket(): %ld\n", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return -1; } iResult = bind (ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("bind failed: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return -1; } freeaddrinfo(result); printf ("*** Pret a recevoir un client ***\n"); // Attend le client if (listen (ListenSocket, SOMAXCONN) == SOCKET_ERROR) { printf( "Error at listen(): %ld\n", WSAGetLastError() ); closesocket(ListenSocket); WSACleanup(); return -1; } ClientSocket = accept (ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("accept failed: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } closesocket(ListenSocket); // N'accepte qu'un seul client printf ("*** Communication debutee avec le client ***\n"); // Crée la partie cliente ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; iResult = getaddrinfo (argv[1], argv[2], &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %d (2)\n", iResult); closesocket(ClientSocket); WSACleanup(); return -1; } ServerSocket = socket (result->ai_family, result->ai_socktype, result->ai_protocol); if (ServerSocket == INVALID_SOCKET) { printf("Error at socket(): %ld (2)\n", WSAGetLastError()); freeaddrinfo(result); closesocket(ClientSocket); WSACleanup(); return -1; } iResult = connect(ServerSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("connect failed: %d\n", iResult); closesocket(ServerSocket); freeaddrinfo(result); closesocket(ClientSocket); WSACleanup(); return -1; } freeaddrinfo(result); if (ServerSocket == INVALID_SOCKET) { printf("Unable to connect to server!\n"); closesocket(ServerSocket); closesocket(ClientSocket); WSACleanup(); return -1; } printf ("*** Communication debutee avec le serveur ***\n"); // Crée les objets de synchronisation Pile = NULL; InitializeCriticalSection (&AccesPile); EtatPile = CreateEvent (NULL, TRUE, FALSE, "EtatPile"); EtatThreadClient = TRUE; EtatThreadServeur = TRUE; // Crée le thread client CreateThread (NULL, 0, ThreadClient, NULL, 0, NULL); // Crée la thread serveur CreateThread (NULL, 0, ThreadServeur, NULL, 0, NULL); for (;;) { WaitForSingleObject (EtatPile, INFINITE); EnterCriticalSection (&AccesPile); switch (Pile->Type) { case T_FROM_SERVER: printf ("Message du serveur : %s", Pile->Contenu); send (ClientSocket, Pile->Contenu, Pile->TailleMessage, 0); break; case T_FROM_CLIENT: printf ("Message du client : %s", Pile->Contenu); send (ServerSocket, Pile->Contenu, Pile->TailleMessage, 0); break; case T_SERVER_END: case T_CLIENT_END: printf ("%s", Pile->Contenu); // Met fin aux connexions closesocket(ServerSocket); closesocket(ClientSocket); break; } MessageTmp = Pile->Suivant; LocalFree (Pile->Contenu); LocalFree (Pile); Pile = MessageTmp; if (Pile == NULL) { if (EtatThreadServeur== FALSE && EtatThreadClient==FALSE) { LeaveCriticalSection (&AccesPile); DeleteCriticalSection (&AccesPile); WSACleanup(); printf ("Fin des communications."); return 0; } ResetEvent (EtatPile); } LeaveCriticalSection (&AccesPile); } } DWORD WINAPI ThreadClient (LPVOID lpParameter) { char Buffer[512]; char Message[513]; int TailleMessage, DebutMessage; int NbrRecvd; int i; MESSAGE **MessageDPtr; UNREFERENCED_PARAMETER (lpParameter); TailleMessage = 0; for (;;) { switch (NbrRecvd = recv (ServerSocket, Buffer+TailleMessage, sizeof(Buffer)-TailleMessage, 0)) { case 0: EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, 256); strcpy_s ((*MessageDPtr)->Contenu, 256, "*** Arret de la connexion cote serveur ***\n"); (*MessageDPtr)->TailleMessage = 256; (*MessageDPtr)->Type = T_SERVER_END; SetEvent (EtatPile); EtatThreadClient = FALSE; LeaveCriticalSection (&AccesPile); return 0; case SOCKET_ERROR: EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, 256); strcpy_s ((*MessageDPtr)->Contenu, 256, "*** Erreur - Fin de la connexion cote serveur ***\n"); (*MessageDPtr)->TailleMessage = 256; (*MessageDPtr)->Type = T_SERVER_END; SetEvent (EtatPile); EtatThreadClient = FALSE; LeaveCriticalSection (&AccesPile); return (DWORD)-1; default: // Découpe le buffer en messages DebutMessage = 0; NbrRecvd = TailleMessage+NbrRecvd; for (i=TailleMessage; i<NbrRecvd; i++) { Message[i-DebutMessage] = Buffer[i]; TailleMessage ++; if (Buffer[i]=='\n') { Message[TailleMessage] = '\0'; EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, TailleMessage+1); strcpy_s ((*MessageDPtr)->Contenu, TailleMessage+1, Message); (*MessageDPtr)->TailleMessage = TailleMessage; (*MessageDPtr)->Type = T_FROM_SERVER; SetEvent (EtatPile); LeaveCriticalSection (&AccesPile); DebutMessage += TailleMessage; TailleMessage = 0; } if (TailleMessage>=512) { EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, 256); strcpy_s ((*MessageDPtr)->Contenu, 256, "*** Erreur: Message trop long - Fin de la connexion cote serveur ***\n"); (*MessageDPtr)->TailleMessage = 256; (*MessageDPtr)->Type = T_SERVER_END; SetEvent (EtatPile); EtatThreadClient = FALSE; LeaveCriticalSection (&AccesPile); return (DWORD)-1; } } } } } DWORD WINAPI ThreadServeur (LPVOID lpParameter) { char Buffer[512]; char Message[513]; int TailleMessage, DebutMessage; int NbrRecvd; int i; MESSAGE **MessageDPtr; UNREFERENCED_PARAMETER (lpParameter); TailleMessage = 0; for (;;) { switch (NbrRecvd = recv (ClientSocket, Buffer+TailleMessage, sizeof(Buffer)-1, 0)) { case 0: EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, 256); strcpy_s ((*MessageDPtr)->Contenu, 256, "*** Arret de la connexion cote client ***\n"); (*MessageDPtr)->TailleMessage = 256; (*MessageDPtr)->Type = T_CLIENT_END; (EtatPile); EtatThreadServeur = FALSE; LeaveCriticalSection (&AccesPile); return 0; case SOCKET_ERROR: EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, 256); strcpy_s ((*MessageDPtr)->Contenu, 256, "*** Erreur - Fin de la connexion cote client ***\n"); (*MessageDPtr)->TailleMessage = 256; (*MessageDPtr)->Type = T_CLIENT_END; SetEvent (EtatPile); EtatThreadServeur= FALSE; LeaveCriticalSection (&AccesPile); return (DWORD)-1; default: // Découpe le buffer en messages DebutMessage = 0; NbrRecvd = TailleMessage+NbrRecvd; for (i=TailleMessage; i<NbrRecvd; i++) { Message[i-DebutMessage] = Buffer[i]; TailleMessage ++; if (Buffer[i]=='\n') { Message[TailleMessage] = '\0'; EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, TailleMessage+1); strcpy_s ((*MessageDPtr)->Contenu, TailleMessage+1, Message); (*MessageDPtr)->TailleMessage = TailleMessage; (*MessageDPtr)->Type = T_FROM_CLIENT; SetEvent (EtatPile); LeaveCriticalSection (&AccesPile); DebutMessage += TailleMessage; TailleMessage = 0; } if (TailleMessage>=512) { EnterCriticalSection (&AccesPile); for (MessageDPtr=&Pile; *MessageDPtr!=NULL; MessageDPtr=&(*MessageDPtr)->Suivant) {}
  • MessageDPtr = LocalAlloc (LMEM_ZEROINIT, sizeof(MESSAGE));
(*MessageDPtr)->Contenu = LocalAlloc (LMEM_ZEROINIT, 256); strcpy_s ((*MessageDPtr)->Contenu, 256, "*** Erreur: Message trop long - Fin de la connexion cote serveur ***\n"); (*MessageDPtr)->TailleMessage = 256; (*MessageDPtr)->Type = T_CLIENT_END; SetEvent (EtatPile); EtatThreadServeur = FALSE; LeaveCriticalSection (&AccesPile); return (DWORD)-1; } } } } }

Conclusion :


N'hésitez pas à donner vos avis et à reporter des problèmes.

A voir également

Ajouter un commentaire

Commentaires

uaip
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
-
Salut,
"Si cela vous gène, n'hésitez pas à envoyer un mail à Microsoft pour leur expliquer à quel point leur crlf fait chier tout le monde."
Ahah, tu marques un point :)
Pas testé ta source, mais ca va bientôt me servir.
Par contre, la directive #pragma comment(), n'est-ce pas uniquement pour le compilo microsoft ?
En tout cas, ça ne fonctionne pas avec (mon) GCC.

Je peaufinerai mes critiques après avoir testé.
Bonne continuation.
_michel
Messages postés
77
Date d'inscription
mardi 27 juin 2006
Statut
Membre
Dernière intervention
12 août 2010
-
UAIP >> C'est vrai, je n'ai pas indiqué le compilateur utilisé (réparé), et c'est tout à fait possible que seul Visual Studio supporte le pragma comment. Pour s'en passer, il faut juste préciser dans les options de link qu'il faut lier ws2_32.lib.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.