📄 cwinsock.cpp
字号:
/*
CWinsock.cpp
Classe base per interfaccia Winsock (SRT/SDK).
Luca Piergentili, 15/07/96
lpiergentili@yahoo.com
http://www.geocities.com/lpiergentili/
La classe viene usata come wrapper per gestire in locale i servizi implementati.
Rimappa l'API Winsock a seconda della definizione della macro _DEBUGSOCKET:
- se non viene definita la macro _DEBUGSOCKET le chiamate Winsock vengono rimappate sull'API originale
- se viene definita la macro _DEBUGSOCKET vengono rimappate le chiamate winsock implementando unicamente i servizi SMTP/POP3
(non viene effettuato nessun controllo sull'esistenza delle directory utilizzate, da create a parte)
*/
#include "CWinsock.h"
#ifdef _DEBUGSOCKET
#include "env.h"
#include "pragma.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "strcpyn.h"
#if defined(_WINDOWS)
#include "window.h"
#else
#include "typedef.h"
#endif
#include <winsock.h>
#include "lmhosts.h"
#include "CDateTime.h"
#define WSA_MAX_SOCKETS 1 // numero max di socket gestiti (1-255)
#define WSA_MAX_MTU 4096 // valore MTU (512-8192)
#define POP3_PORT 110 // porta POP3
#define SMTP_PORT 25 // porta SMTP
#define BUF_SIZE 1048576 // dimensione del buffer per la lettura dal file (POP3)
#define MAX_DELE_MARK 512 // numero max di mark per il comando DELE
#ifdef _WINNT
#define MAIL_DIRECTORY "c:\\inetpub\\mail\\" // directory per le mailbox
#else
#define MAIL_DIRECTORY "c:\\webshare\\mail\\"
#endif
#define SOCKET_FILE MAIL_DIRECTORY"log\\socket.txt" // file per il socket
#define COUNT_FILE "tot.txt" // file per i totali
#define USERS_FILE "users.txt" // file utenti
#define MAX_USR_LEN 20 // lunghezza max nome utente
#define MAX_EMAIL_LEN 35 // lunghezza max email
#define CRLF_LEN 2 // CR+LF
#define USR_ENTRY_LEN (MAX_USR_LEN+MAX_EMAIL_LEN+CRLF_LEN) // dimensione del record
/*
CWinsock()
*/
CWinsock::CWinsock()
{
iWSALastError = 0;
iWSAFlag = 0;
hFile = HFILE_ERROR;
hSocket = INVALID_SOCKET;
pHostName = LOCAL_HOST_NAME;
pHostIp = LOCAL_HOST;
iService = -1;
iCommand = 0;
pHostLastSend = new char[WSA_MAX_MTU + 1];
memset(pHostLastSend,'\0',WSA_MAX_MTU + 1);
pHostLastRecv = new char[WSA_MAX_MTU + 1];
memset(pHostLastRecv,'\0',WSA_MAX_MTU + 1);
pPop3Buffer = new char[BUF_SIZE + 1];
memset(pPop3Buffer,'\0',BUF_SIZE + 1);
bRetr = FALSE;
hMailBox = HFILE_ERROR;
pMailBox = new char[MAX_EMAIL_LEN + 1];
memset(pMailBox,'\0',MAX_EMAIL_LEN + 1);
iTotMail = 0;
iDelArray = new int[MAX_DELE_MARK + 1];
memset(iDelArray,'\0',MAX_DELE_MARK + 1);
iDelIndex = -1;
date.Reset();
}
/*
~CWinsock()
*/
CWinsock::~CWinsock()
{
if(pHostLastSend)
delete [] pHostLastSend,pHostLastSend = NULL;
if(pHostLastRecv)
delete [] pHostLastRecv,pHostLastRecv = NULL;
if(pPop3Buffer)
delete [] pPop3Buffer,pPop3Buffer = NULL;
if(pMailBox)
delete [] pMailBox,pMailBox = NULL;
if(iDelArray)
delete [] iDelArray,iDelArray = NULL;
}
/*
WSAStartup()
*/
int PASCAL FAR CWinsock::WSAStartup(WORD wVersionRequired,LPWSADATA lpWSAData)
{
lpWSAData->wVersion = MAKEWORD(1,1); // versione
lpWSAData->wHighVersion = MAKEWORD(1,1); // versione
lstrcpy(lpWSAData->szDescription,"Dummy Winsock library v.1.0"); // vendor info
lstrcpy(lpWSAData->szSystemStatus,"Written by Luca Piergentili");// more info
lpWSAData->iMaxSockets = WSA_MAX_SOCKETS; // numero massimo di socket supportati
lpWSAData->iMaxUdpDg = WSA_MAX_MTU; // valore MTU
lpWSAData->lpVendorInfo = NULL; // struttura fornita dal vendor
iWSAFlag = 1;
return(0);
}
/*
WSACleanup()
*/
int PASCAL FAR CWinsock::WSACleanup(void)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
else
return(0);
}
/*
WSASetLastError()
*/
void PASCAL FAR CWinsock::WSASetLastError(int iError)
{
iWSALastError = iError;
}
/*
WSAGetLastError()
*/
int PASCAL FAR CWinsock::WSAGetLastError(void)
{
return(iWSALastError);
}
/*
setsockopt()
*/
int CWinsock::setsockopt(SOCKET s,int level,int optname,const char FAR *optval,int optlen)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
else
return(0);
}
/*
socket()
Creazione del socket.
*/
SOCKET PASCAL FAR CWinsock::socket(int af,int type,int protocol)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(INVALID_SOCKET);
}
// controlla gli specificatori del socket
if(af!=PF_INET)
{
WSASetLastError(WSAEAFNOSUPPORT);
return(INVALID_SOCKET);
}
if(type!=SOCK_STREAM && type!=SOCK_DGRAM)
{
WSASetLastError(WSAESOCKTNOSUPPORT);
return(INVALID_SOCKET);
}
// implementa il socket su file
if((hFile = _lcreat(SOCKET_FILE,0))==HFILE_ERROR)
{
WSASetLastError(WSAEBADF);
hSocket = INVALID_SOCKET;
}
else
hSocket = WSA_MAX_SOCKETS;
return(hSocket);
}
/*
getsockname()
*/
int CWinsock::getsockname(SOCKET s,struct sockaddr FAR *name,int FAR *namelen)
{
return(SOCKET_ERROR);
}
/*
connect()
*/
int PASCAL FAR CWinsock::connect(SOCKET s,const struct sockaddr FAR *name,int namelen)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
// controlla che il socket (ossia il file) sia stato aperto
if(hFile==HFILE_ERROR)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
// errore sul socket
if(s==INVALID_SOCKET)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
else if(s==WSA_MAX_SOCKETS)
{
// implementa solo i servizi SMTP/POP3
if(iService!=SMTP_PORT && iService!=POP3_PORT)
{
WSASetLastError(WSAEPROTONOSUPPORT);
return(SOCKET_ERROR);
}
else
{
// imposta per il comando successivo
strcpy(pHostLastSend,"CONNECT");
return(0);
}
}
else
{
WSASetLastError(WSAEISCONN);
return(SOCKET_ERROR);
}
}
/*
shutdown()
*/
int CWinsock::shutdown(SOCKET s,int how)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
else
return(0);
}
/*
closesocket()
*/
int FAR PASCAL CWinsock::closesocket(SOCKET s)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
// controlla che il socket (ossia il file) sia stato aperto
if(hFile==HFILE_ERROR)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
// errore sul socket
if(s==INVALID_SOCKET)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
else if(s==WSA_MAX_SOCKETS)
{
_lclose(hFile);
hFile = HFILE_ERROR;
hSocket = INVALID_SOCKET;
return(0);
}
else
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
}
/*
send()
*/
int PASCAL FAR CWinsock::send(SOCKET s,const char FAR *buf,int len,int flags)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
// controlla che il socket (ossia il file) sia stato aperto
if(hFile==HFILE_ERROR)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
// errore sul socket
if(s==INVALID_SOCKET)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
else if(s==WSA_MAX_SOCKETS)
{
// invia i dati all'host tracciando il socket su file
if(send_to_host(buf,len)!=0)
{
WSASetLastError(WSANO_DATA);
return(SOCKET_ERROR);
}
else
return(_lwrite(hFile,buf,len));
}
else
{
WSASetLastError(WSAENOTCONN);
return(SOCKET_ERROR);
}
}
/*
recv()
*/
int PASCAL FAR CWinsock::recv(SOCKET s,char FAR *buf,int len,int flags)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
// controlla che il socket (ossia il file) sia stato aperto
if(hFile==HFILE_ERROR)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
// errore sul socket
if(s==INVALID_SOCKET)
{
WSASetLastError(WSAENOTSOCK);
return(SOCKET_ERROR);
}
else if(s==WSA_MAX_SOCKETS)
{
// riceve i dati dall'host tracciando il socket su file
if(recv_from_host(buf,len)!=0)
{
WSASetLastError(WSANO_DATA);
return(SOCKET_ERROR);
}
else
return(_lwrite(hFile,(const char FAR *)buf,strlen(buf)));
}
else
{
WSASetLastError(WSAENOTCONN);
return(SOCKET_ERROR);
}
}
/*
gethostbyname()
*/
struct hostent FAR * PASCAL FAR CWinsock::gethostbyname(const char FAR *name)
{
static char* host_alias[] = {NULL,NULL};
static struct in_addr st_addr;
st_addr.S_un.S_addr = LOCAL_HOST_NUM;
static char* host_names[] = {(char FAR *)&st_addr,NULL};
static struct hostent host_ent_struct = {0};
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return((struct hostent FAR *)NULL);
}
else
{
// imposta la struttura
host_ent_struct.h_name = pHostName;
host_ent_struct.h_aliases = host_alias;
host_ent_struct.h_addrtype = PF_INET;
host_ent_struct.h_length = 4;
host_ent_struct.h_addr_list = host_names;
return((struct hostent FAR *)&host_ent_struct);
}
}
/*
gethostbyaddr()
*/
struct hostent FAR * CWinsock::gethostbyaddr(const char FAR *addr,int len,int type)
{
return(gethostbyname(NULL));
}
/*
gethostname()
*/
int PASCAL FAR CWinsock::gethostname(char FAR *name,int namelen)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(SOCKET_ERROR);
}
else
{
strcpyn(name,pHostName,namelen);
return(0);
}
}
/*
getservbyname()
*/
struct servent FAR * CWinsock::getservbyname(const char FAR *name,const char FAR *proto)
{
static struct servent se;
se.s_port = -1;
return(&se);
}
/*
getservbyport()
*/
struct servent FAR * CWinsock::getservbyport(int port,const char FAR *proto)
{
static struct servent se;
se.s_name = "???";
return(&se);
}
/*
htons()
*/
u_short PASCAL FAR CWinsock::htons(u_short hostshort)
{
// imposta il servizio
iService = hostshort;
return(hostshort);
}
/*
inet_addr()
*/
unsigned long PASCAL FAR CWinsock::inet_addr(const char FAR *cp)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return(INADDR_NONE);
}
else
return(LOCAL_HOST_NUM);
}
/*
inet_ntoa()
*/
char FAR * CWinsock::inet_ntoa(struct in_addr in)
{
if(!iWSAFlag)
{
WSASetLastError(WSANOTINITIALISED);
return((char FAR *)NULL);
}
else
return(pHostIp);
}
/*
send_to_host()
Utilizzata per inviare i dati all'host.
I dati vengono registrati nella directory relativa alla casella email.
Che l'handle del file per la mailbox sia chiuso (HFILE_ERROR) non viene considerato un
errore, dato che la funzione viene utilizzata anche per inviare i comandi al server.
*/
int CWinsock::send_to_host(const char FAR *buf,int len)
{
// controlla il servizio
if(iService < 0)
{
WSASetLastError(WSAEPROTONOSUPPORT);
return(1);
}
// imposta per il comando successivo
if(strstr(buf,"\r\n.\r\n")!=NULL)
strcpy(pHostLastSend,"END");
else
strcpyn(pHostLastSend,buf,WSA_MAX_MTU + 1);
// registra i dati nella mailbox
// il file viene aperto alla ricezione del comando DATA e chiuso con il comando END
if(hMailBox!=HFILE_ERROR)
_lwrite(hMailBox,buf,len);
return(0);
}
/*
recv_from_host()
Utilizzata per ricevere i dati dall'host.
I dati vengono prelevati dalla directory relativa alla casella email.
*/
int CWinsock::recv_from_host(char FAR * buf,int len)
{
int ret = 0;
static int tot = 0;
// controlla che il servizio sia tra quelli gestiti, rispondendo al comando
switch(iService)
{
/*
SMTP
- il messaggio non puo' eccedere i BUF_SIZE caratteri (per POP3)
- supporta un solo destinatario per volta (non supporta ne' Cc: ne' Bcc:)
- il comando RCPT TO non controlla l'esistenza dell'email
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -