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.
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.