// Mail Proxy Service
#include
#include
#include
#include
#include
#include
// 定数定義
#define FILE_NO_MAX 20
#define POP_DATA_FILE "c:\\usr\\bin\\maildata_p."
#define SMTP_DATA_FILE "c:\\usr\\bin\\maildata_s."
#define SV_IP_ADDR "172.16.39.92"
#define POP_PX_PORT (u_short) 60110
#define POP_PORT (u_short) 110
#define SMTP_PX_PORT (u_short) 60025
#define SMTP_PORT (u_short) 25
#define MAX_BUFF_SIZE 640
#define MAX_DATA_SIZE 65536
// スレッドパラメータ
typedef struct _ThreadPrm{
SOCKADDR_IN serverSockAddr;
SOCKET serverSocket;
SOCKET clientSocket;
}ThreadPrm;
// グローバル変数。
// ファイル番号
unsigned int sfile_no = 0;
unsigned int pfile_no = 0;
// サービスの名前。
char *MAILPROXY_S = "MailProxy_S";
char *MAILPROXY_P = "MailProxy_P";
// 中継先メールサーバアドレス
//// メモリリード衝突回避のため2つ
char sv_ip_addr_s[MAX_BUFF_SIZE];
char sv_ip_addr_p[MAX_BUFF_SIZE];
// ServiceMainが完了するのを防止するために使用するイベント。
HANDLE MailProxyS_terminateEvent = NULL;
HANDLE MailProxyP_terminateEvent = NULL;
// 状態情報をSCMとの間で通知し合うために使用するハンドル。
// RegisterServiceCtrlHandler関数によって作成される。
SERVICE_STATUS_HANDLE serviceStatusHandle;
// サービスの現在の状態を格納するフラグ。
BOOL pauseService = FALSE;
BOOL runningService = FALSE;
// 実際の処理を行うためのスレッド。
HANDLE MailProxyS_threadHandle = 0;
HANDLE MailProxyP_threadHandle = 0;
//関数プロトタイプ
int sock_addr_ini(struct sockaddr_in *,unsigned long,unsigned short);
int socket_close( SOCKET );
unsigned long send_loop(SOCKET,void *,unsigned int);
int recv_with_term(SOCKET ,unsigned char ,void *);
int send_with_term(SOCKET ,unsigned char ,void *);
VOID talkToClient_P(VOID *);
VOID talkToClient_S(VOID *);
VOID talkToClient_P(VOID *prm)
{
char sv_buff[MAX_BUFF_SIZE],cl_buff[MAX_BUFF_SIZE];
char data_buff[MAX_DATA_SIZE];
char mail_data_file[MAX_BUFF_SIZE];
int status;
int wpoint;
ThreadPrm threadprm;
SOCKADDR_IN serverSockAddr;
SOCKET serverSocket;
SOCKET clientSocket;
FILE *fp;
memcpy((void *)&threadprm,prm,sizeof(ThreadPrm));
serverSockAddr = threadprm.serverSockAddr;
serverSocket = threadprm.serverSocket;
clientSocket = threadprm.clientSocket;
memset(sv_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
serverSocket,
'\n',
(void *)sv_buff
);
status = send_with_term
(
clientSocket,
'\n',
(void *)sv_buff
);
while(1){
memset(cl_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
clientSocket,
'\n',
(void *)cl_buff
);
if(!strncmp(cl_buff,"LIST",4)){
status = send_with_term
(
serverSocket,
'\n',
(void *)cl_buff
);
//printf("=>[%s]\n",data_buff);
memset(data_buff,0x00,MAX_DATA_SIZE);
wpoint = 0;
while(1){
status = recv
(
serverSocket,
&data_buff[wpoint],
1,
0
);
//printf("%c",data_buff[wpoint]);
if((wpoint > 3)
&&(data_buff[wpoint-3] == 0x0a
&& data_buff[wpoint-2] == '.'
&& data_buff[wpoint-1] == 0x0d
&& data_buff[wpoint] == 0x0a)){
break;
}
wpoint++;
}
status = send_loop
(
clientSocket,
(void *)data_buff,
strlen(data_buff)
);
}else if(!strncmp(cl_buff,"RETR",4)){
status = send_with_term
(
serverSocket,
'\n',
(void *)cl_buff
);
memset(sv_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
serverSocket,
'\n',
(void *)sv_buff
);
status = send_with_term
(
clientSocket,
'\n',
(void *)sv_buff
);
memset(data_buff,0x00,MAX_DATA_SIZE);
wpoint = 0;
while(1){
status = recv
(
serverSocket,
&data_buff[wpoint],
1,
0
);
//printf("%c",data_buff[wpoint]);
if((wpoint > 3)
&&(data_buff[wpoint-3] == 0x0a
&& data_buff[wpoint-2] == '.'
&& data_buff[wpoint-1] == 0x0d
&& data_buff[wpoint] == 0x0a)){
break;
}
wpoint++;
}
status = send_loop
(
clientSocket,
(void *)data_buff,
strlen(data_buff)
);
memset(mail_data_file,0x00,MAX_BUFF_SIZE);
sprintf(mail_data_file,"%s%04d",POP_DATA_FILE,pfile_no);
pfile_no++;
if(pfile_no>FILE_NO_MAX){
pfile_no=0;
}
if(NULL==(fp = fopen(mail_data_file,"w"))){
printf("can't open pw file\n");
}else{
fprintf(fp,"%s\n",data_buff);
fclose(fp);
}
}else{
status = send_with_term
(
serverSocket,
'\n',
(void *)cl_buff
);
//printf("cl -> sv ===>[%s]\n",cl_buff);
memset(sv_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
serverSocket,
'\n',
(void *)sv_buff
);
//printf("===>[%s]\n",sv_buff);
status = send_with_term
(
clientSocket,
'\n',
(void *)sv_buff
);
//printf("sv -> cl ===>[%s]\n",sv_buff);
if(!strncmp(cl_buff,"QUIT",4)){
wpoint = 0;
socket_close( serverSocket );
socket_close( clientSocket );
_endthread();
}
}
}
}
VOID talkToClient_S(VOID *cs)
{
char sv_buff[MAX_BUFF_SIZE],cl_buff[MAX_BUFF_SIZE];
char data_buff[MAX_DATA_SIZE];
char smtp_data_file[MAX_BUFF_SIZE];
int status;
int wpoint;
SOCKADDR_IN serverSockAddr;
SOCKET serverSocket;
SOCKET clientSocket = (SOCKET) cs;
FILE *fp;
//MailServerとの接続
memset(&serverSockAddr,0x00,sizeof(struct sockaddr_in));
serverSocket = socket( AF_INET,SOCK_STREAM,0 );
if (serverSocket == INVALID_SOCKET)
{
cerr << "エラー: socketの実行が失敗しました。" << endl;
status = WSACleanup();
if (status == SOCKET_ERROR){
cerr << "エラー: WSACleanupの実行が失敗しました。"<< endl;
_endthread();
}
}
sock_addr_ini
(
(struct sockaddr_in *)&serverSockAddr,
inet_addr(sv_ip_addr_s),
htons(SMTP_PORT)
);
status = connect
(
serverSocket,
(struct sockaddr *)&serverSockAddr,
sizeof(serverSockAddr)
);
if(status != 0){
cout << "接続できませんでした。" << endl;
socket_close(serverSocket);
socket_close(clientSocket);
_endthread();
}
memset(sv_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
serverSocket,
'\n',
(void *)sv_buff
);
status = send_with_term
(
clientSocket,
'\n',
(void *)sv_buff
);
while(1){
memset(cl_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
clientSocket,
'\n',
(void *)cl_buff
);
status = send_with_term
(
serverSocket,
'\n',
(void *)cl_buff
);
//printf("==>[%s]\n",data_buff);
memset(sv_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
serverSocket,
'\n',
(void *)sv_buff
);
status = send_with_term
(
clientSocket,
'\n',
(void *)sv_buff
);
//printf("<==[%s]\n",temp_buff);
if(!strncmp(cl_buff,"QUIT",4)){
socket_close(serverSocket);
socket_close(clientSocket);
_endthread();
}
memset(data_buff,0x00,MAX_DATA_SIZE);
if(!strncmp(cl_buff,"DATA",4)){
//データ送信
wpoint=0;
memset(data_buff,0x00,MAX_DATA_SIZE);
while(1){
status = recv
(
clientSocket,
&data_buff[wpoint],
1,
0
);
//printf("%c",data_buff[wpoint]);
if((wpoint > 3)
&&(data_buff[wpoint-3] == 0x0a
&& data_buff[wpoint-2] == '.'
&& data_buff[wpoint-1] == 0x0d
&& data_buff[wpoint] == 0x0a)){
break;
}
wpoint++;
}
sprintf(smtp_data_file,"%s%04d",SMTP_DATA_FILE,sfile_no);
sfile_no++;
if(sfile_no>FILE_NO_MAX){
sfile_no=0;
}
if(NULL==(fp = fopen(smtp_data_file,"w"))){
printf("can't open sw file\n");
}else{
fprintf(fp,"%s\n",data_buff);
fclose(fp);
}
status = send_loop
(
serverSocket,
data_buff,
strlen(data_buff)
);
memset(sv_buff,0x00,MAX_BUFF_SIZE);
status = recv_with_term
(
serverSocket,
'\n',
(void *)sv_buff
);
// check status = 354
status = send_with_term
(
clientSocket,
'\n',
(void *)sv_buff
);
memset(smtp_data_file,0x00,MAX_DATA_SIZE);
wpoint = 0;
}
}
}
// ErrorHandler
void ErrorHandler(char *s, DWORD err)
{
cout << s << endl;
cout << "エラー番号: " << err << endl;
ExitProcess(err);
}
DWORD MailProxyS_Thread(LPDWORD param)
{
// WSADATA Data;
SOCKADDR_IN proxySockAddr;
SOCKET proxySocket;
SOCKET clientSocket;
int addrLen = sizeof(struct sockaddr);
int status;
DWORD threadID;
// ソケットを作成する。
proxySocket = socket(AF_INET, SOCK_STREAM, 0);
if (proxySocket == INVALID_SOCKET)
{
cerr << "エラー: socketの実行が失敗しました。"<< endl;
status = WSACleanup();
if (status == SOCKET_ERROR){
cerr << "エラー: WSACleanupの実行が失敗しました。"<< endl;
return(1);
}
}
sock_addr_ini
(
(struct sockaddr_in *)&proxySockAddr,
0,
htons(SMTP_PX_PORT)
);
// ソケットをアドレスと関連付ける。
status = bind(
proxySocket,
(LPSOCKADDR) &proxySockAddr,
sizeof(proxySockAddr)
);
if (status == SOCKET_ERROR)
cerr << "エラー: bindの実行が失敗しました。" << endl;
// ソケットで接続を受け付けることを可能にする。
status = listen(proxySocket, 3);
if (status == SOCKET_ERROR)
cerr << "エラー: listenの実行が失敗しました。" << endl;
while(1)
{
// 接続要求を受け取ったら,その要求を受け付ける。
clientSocket = accept(
proxySocket,
//(LPSOCKADDR) &proxySocket,
(struct sockaddr *)&proxySockAddr,
&addrLen
);
if (clientSocket == INVALID_SOCKET)
{
cerr << "エラー: 接続を受け付けることができません。"<< endl;
return(1);
}
threadID = _beginthread
(
talkToClient_S,
0,
(VOID *) clientSocket
);
if (threadID == -1){
cerr << "エラー: スレッドを作成できません。"<< endl;
// ソケットを閉じる。
socket_close(clientSocket);
}
} // whileループ
return 0;
}
DWORD MailProxyP_Thread(LPDWORD param)
{
// WSADATA Data;
SOCKADDR_IN serverSockAddr;
SOCKET serverSocket;
SOCKADDR_IN proxySockAddr;
SOCKET proxySocket;
SOCKET clientSocket;
int addrLen = sizeof(struct sockaddr);
int status;
DWORD threadID;
ThreadPrm threadPrm;
// ソケットを作成する。
proxySocket = socket(AF_INET, SOCK_STREAM, 0);
if (proxySocket == INVALID_SOCKET)
{
cerr << "エラー: socketの実行が失敗しました。"<< endl;
status = WSACleanup();
if (status == SOCKET_ERROR)
cerr << "エラー: WSACleanupの実行が失敗しました。"<< endl;
return(1);
}
sock_addr_ini
(
(struct sockaddr_in *)&proxySockAddr,
0,
htons(POP_PX_PORT)
);
// ソケットをアドレスと関連付ける。
status = bind(proxySocket,
(LPSOCKADDR) &proxySockAddr,
sizeof(proxySockAddr));
if (status == SOCKET_ERROR)
cerr << "エラー: bindの実行が失敗しました。" << endl;
// ソケットで接続を受け付けることを可能にする。
status = listen(proxySocket, 3);
if (status == SOCKET_ERROR)
cerr << "エラー: listenの実行が失敗しました。" << endl;
while(1)
{
// 接続要求を受け取ったら,その要求を
// 受け付ける。
clientSocket = accept(proxySocket,
// (LPSOCKADDR) &proxySocket,
(struct sockaddr *)&proxySockAddr,
&addrLen);
if (clientSocket == INVALID_SOCKET)
{
cerr << "エラー: 接続を受け付けることができません。"<< endl;
return(1);
}
//MailServerとの接続
memset(&serverSockAddr,0x00,sizeof(struct sockaddr_in));
serverSocket = socket( AF_INET,SOCK_STREAM,0 );
if (serverSocket == INVALID_SOCKET)
{
cerr << "エラー: socketの実行が失敗しました。" << endl;
status = WSACleanup();
if (status == SOCKET_ERROR){
cerr << "エラー: WSACleanupの実行が失敗しました。"<< endl;
break;
}
}
sock_addr_ini
(
(struct sockaddr_in *)&serverSockAddr,
inet_addr(sv_ip_addr_p),
htons(POP_PORT)
);
status = connect
(
serverSocket,
(struct sockaddr *)&serverSockAddr,
sizeof(serverSockAddr)
);
if(status != 0){
cout << "接続できませんでした。" << endl;
socket_close(serverSocket);
socket_close(clientSocket);
break;
}
threadPrm.serverSockAddr = serverSockAddr;
threadPrm.serverSocket = serverSocket;
threadPrm.clientSocket = clientSocket;
threadID = _beginthread
(
talkToClient_P,
0,
(VOID *)&threadPrm
);
if (threadID == -1){
cerr << "エラー: スレッドを作成できません。"<< endl;
// ソケットを閉じる。
socket_close(clientSocket);
}
} // whileループ
return 0;
}
// サービスを初期化するためにそのスレッドを開始する。
BOOL InitService()
{
DWORD id;
// サービスのスレッドを開始する。
MailProxyS_threadHandle = CreateThread(0, 0,
(LPTHREAD_START_ROUTINE) MailProxyS_Thread,
0, 0, &id);
MailProxyP_threadHandle = CreateThread(0, 0,
(LPTHREAD_START_ROUTINE) MailProxyP_Thread,
0, 0, &id);
if (MailProxyS_threadHandle==0 || MailProxyP_threadHandle == 0)
return FALSE;
else
{
runningService = TRUE;
return TRUE;
}
}
// 一時停止されたサービスを再開する。
VOID ResumeService()
{
pauseService=FALSE;
ResumeThread(MailProxyS_threadHandle);
ResumeThread(MailProxyP_threadHandle);
}
// サービスを一時停止する。
VOID PauseService()
{
pauseService = TRUE;
SuspendThread(MailProxyS_threadHandle);
SuspendThread(MailProxyP_threadHandle);
}
// ServiceMain関数を完了させることによって、サービスを
// 停止する。
VOID StopService()
{
runningService=FALSE;
// ServiceMain関数が制御を返すことができるようにするために
// ServiceMain関数が完了するのを防止しているイベントをセットする。
SetEvent(MailProxyS_terminateEvent);
SetEvent(MailProxyP_terminateEvent);
}
// この関数は、SetServiceStatus関数によって
// サービスの状態を更新する処理をまとめて
// 実行する。
BOOL SendStatusToSCM (DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwServiceSpecificExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint)
{
BOOL success;
SERVICE_STATUS serviceStatus;
// SERVICE_STATUS構造体のすべてのメンバに値を設定する。
// サービススレッドが複数の場合はSERVICE_WIN32_SHARE_PROCESSを使用する!!!
//serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;//←複数のサービススレッドを実装する場合
serviceStatus.dwCurrentState = dwCurrentState;
// 何らかの処理を行っている場合は、コントロールイベントを受け
// 取らない。それ以外の場合は、コントロールイベントを受け取る。
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwControlsAccepted = 0;
else
serviceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN;
// 特定の終了コードが定義されている場合は、
// win32の終了コードを正しく設定する。
if (dwServiceSpecificExitCode == 0)
serviceStatus.dwWin32ExitCode =
dwWin32ExitCode;
else
serviceStatus.dwWin32ExitCode =
ERROR_SERVICE_SPECIFIC_ERROR;
serviceStatus.dwServiceSpecificExitCode =
dwServiceSpecificExitCode;
serviceStatus.dwCheckPoint = dwCheckPoint;
serviceStatus.dwWaitHint = dwWaitHint;
// 状態レコードをSCMに渡す。
success = SetServiceStatus (serviceStatusHandle,
&serviceStatus);
if (!success)
StopService();
return success;
}
// サービスコントロールマネージャから受け取ったイベントを
// ディスパッチする。
VOID MailProxyS_CtrlHandler (DWORD controlCode)
{
DWORD currentState = 0;
BOOL success;
switch(controlCode)
{
// 開始時にはServiceMain関数が呼び出されるので
// START(開始)オプションはない。
// サービスを停止する。
case SERVICE_CONTROL_STOP:
currentState = SERVICE_STOP_PENDING;
// 現在の状態をSCMに通知する。
success = SendStatusToSCM(
SERVICE_STOP_PENDING,
NO_ERROR, 0, 1, 5000);
// 成功しなかった場合、特に何も行わない。
// サービスを停止する。
StopService();
return;
// サービスを一時停止する。
case SERVICE_CONTROL_PAUSE:
if (runningService && !pauseService)
{
// 現在の状態をSCMに通知する。
success = SendStatusToSCM(
SERVICE_PAUSE_PENDING,
NO_ERROR, 0, 1, 1000);
PauseService();
currentState = SERVICE_PAUSED;
}
break;
// 一時停止から再開する。
case SERVICE_CONTROL_CONTINUE:
if (runningService && pauseService)
{
// 現在の状態をSCMに通知する。
success = SendStatusToSCM(
SERVICE_CONTINUE_PENDING,
NO_ERROR, 0, 1, 1000);
ResumeService();
currentState = SERVICE_RUNNING;
}
break;
// 現在の状態を更新する。
case SERVICE_CONTROL_INTERROGATE:
// このswitch文の後の行に進み、状態を送信する。
break;
// シャットダウン時には何もしない。ここでクリーンアップを
// 行うことができるが、非常にすばやく行わなければならない。
case SERVICE_CONTROL_SHUTDOWN:
// シャットダウン時には何もしない。
return;
default:
break;
}
SendStatusToSCM(currentState, NO_ERROR,
0, 0, 0);
}
// サービスコントロールマネージャから受け取ったイベントを
// ディスパッチする。
VOID MailProxyP_CtrlHandler (DWORD controlCode)
{
DWORD currentState = 0;
BOOL success;
switch(controlCode)
{
// 開始時にはServiceMain関数が呼び出されるので
// START(開始)オプションはない。
// サービスを停止する。
case SERVICE_CONTROL_STOP:
currentState = SERVICE_STOP_PENDING;
// 現在の状態をSCMに通知する。
success = SendStatusToSCM(
SERVICE_STOP_PENDING,
NO_ERROR, 0, 1, 5000);
// 成功しなかった場合、特に何も行わない。
// サービスを停止する。
StopService();
return;
// サービスを一時停止する。
case SERVICE_CONTROL_PAUSE:
if (runningService && !pauseService)
{
// 現在の状態をSCMに通知する。
success = SendStatusToSCM(
SERVICE_PAUSE_PENDING,
NO_ERROR, 0, 1, 1000);
PauseService();
currentState = SERVICE_PAUSED;
}
break;
// 一時停止から再開する。
case SERVICE_CONTROL_CONTINUE:
if (runningService && pauseService)
{
// 現在の状態をSCMに通知する。
success = SendStatusToSCM(
SERVICE_CONTINUE_PENDING,
NO_ERROR, 0, 1, 1000);
ResumeService();
currentState = SERVICE_RUNNING;
}
break;
// 現在の状態を更新する。
case SERVICE_CONTROL_INTERROGATE:
// このswitch文の後の行に進み、状態を送信する。
break;
// シャットダウン時には何もしない。ここでクリーンアップを
// 行うことができるが、非常にすばやく行わなければならない。
case SERVICE_CONTROL_SHUTDOWN:
// シャットダウン時には何もしない。
return;
default:
break;
}
SendStatusToSCM(currentState, NO_ERROR,
0, 0, 0);
}
// ServiceMain関数でエラーが発生した場合の処理として、クリーンアップを
// 行い、サービスが開始しなかったことをSCMに通知する。
VOID terminate(DWORD error)
{
// terminateEventハンドルが作成されている場合は、それを閉じる。
if (MailProxyS_terminateEvent)
CloseHandle(MailProxyS_terminateEvent);
if (MailProxyP_terminateEvent)
CloseHandle(MailProxyP_terminateEvent);
// サービスが停止したことを通知するために、
// SCMにメッセージを送信する。
if (serviceStatusHandle)
SendStatusToSCM(SERVICE_STOPPED, error,
0, 0, 0);
// スレッドが開始されている場合は、それを終了する。
if (MailProxyS_threadHandle)
CloseHandle(MailProxyS_threadHandle);
if (MailProxyP_threadHandle)
CloseHandle(MailProxyP_threadHandle);
// serviceStatusHandleハンドルは閉じる必要がない。
}
// ServiceMain関数は、SCMがサービスを開始するときに
// 呼び出される。ServiceMain関数が制御を返すと、サービスは
// 停止する。したがって、関数の実行が終了する直前まで、
// ServiceMain関数はイベントを待機している状態にしておき、
// 停止するときになったら、そのイベントをシグナル状態にセットする。
// また、エラーが発生した場合にはサービスを開始できないので、
// エラーが発生した場合にもServiceMain関数は制御を返す。
VOID mail_proxy_s_main(DWORD argc, LPTSTR *argv)
{
BOOL success;
// 即座に登録関数を呼び出す。
serviceStatusHandle =
RegisterServiceCtrlHandler(
MAILPROXY_S,
(LPHANDLER_FUNCTION)MailProxyS_CtrlHandler);
if (!serviceStatusHandle)
{
terminate(GetLastError());
return;
}
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR, 0, 1, 5000);
if (!success)
{
terminate(GetLastError());
return;
}
// 終了イベントを作成する。
MailProxyS_terminateEvent = CreateEvent (0, TRUE, FALSE, 0);
if (!MailProxyS_terminateEvent)
{
terminate(GetLastError());
return;
}
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR, 0, 2, 1000);
if (!success)
{
terminate(GetLastError());
return;
}
// 開始パラメータの有無をチェックする。
memset(sv_ip_addr_s,0x00,MAX_BUFF_SIZE);
memset(sv_ip_addr_p,0x00,MAX_BUFF_SIZE);
if (argc < 2)
{
strcpy(sv_ip_addr_s,SV_IP_ADDR);
strcpy(sv_ip_addr_p,SV_IP_ADDR);
}else{
strcpy(sv_ip_addr_s,argv[1]);
strcpy(sv_ip_addr_p,argv[1]);
}
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR, 0, 3, 5000);
if (!success)
{
terminate(GetLastError());
return;
}
// サービス自体を開始する。
success = InitService();
if (!success)
{
terminate(GetLastError());
return;
}
// この時点でサービスは実行状態になっている。
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_RUNNING,
NO_ERROR, 0, 0, 0);
if (!success)
{
terminate(GetLastError());
return;
}
// 終了シグナルを待機し、それを検出したら終了する。
WaitForSingleObject (MailProxyS_terminateEvent, INFINITE);
terminate(0);
}
VOID mail_proxy_p_main(DWORD argc, LPTSTR *argv)
{
BOOL success;
// 即座に登録関数を呼び出す。
serviceStatusHandle =
RegisterServiceCtrlHandler(
MAILPROXY_P,
(LPHANDLER_FUNCTION)MailProxyP_CtrlHandler);
if (!serviceStatusHandle)
{
terminate(GetLastError());
return;
}
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR, 0, 1, 5000);
if (!success)
{
terminate(GetLastError());
return;
}
// 終了イベントを作成する。
MailProxyP_terminateEvent = CreateEvent (0, TRUE, FALSE, 0);
if (!MailProxyP_terminateEvent)
{
terminate(GetLastError());
return;
}
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR, 0, 2, 1000);
if (!success)
{
terminate(GetLastError());
return;
}
FILE *fpDebug;
fpDebug = fopen("c:\\usr\\bin\\pDebug.txt","w");
fprintf(fpDebug,"*** start\n");
// 開始パラメータの有無をチェックする。
/* if (argc < 2)
{
memset(sv_ip_addr_p,0x00,MAX_BUFF_SIZE);
strcpy(sv_ip_addr_p,SV_IP_ADDR);
}else{
memset(sv_ip_addr_p,0x00,MAX_BUFF_SIZE);
strcpy(sv_ip_addr_p,argv[1]);
}
*/
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR, 0, 3, 5000);
if (!success)
{
terminate(GetLastError());
return;
}
// サービス自体を開始する。
success = InitService();
if (!success)
{
terminate(GetLastError());
return;
}
// この時点でサービスは実行状態になっている。
// 進捗状況をSCMに通知する。
success = SendStatusToSCM(
SERVICE_RUNNING,
NO_ERROR, 0, 0, 0);
if (!success)
{
terminate(GetLastError());
return;
}
// 終了シグナルを待機し、それを検出したら終了する。
WaitForSingleObject (MailProxyP_terminateEvent, INFINITE);
terminate(0);
}
/*****************************************************************************/
/****** MAIN *****************************************************************/
/*****************************************************************************/
VOID main(VOID)
{
SERVICE_TABLE_ENTRY serviceTable[] =
{
{ MAILPROXY_S, (LPSERVICE_MAIN_FUNCTION) mail_proxy_s_main},
{ MAILPROXY_P, (LPSERVICE_MAIN_FUNCTION) mail_proxy_p_main},
{ NULL, NULL }
};
BOOL success;
WSADATA Data;
int status;
// WindowsソケットDLLを初期化する。
status = WSAStartup(MAKEWORD(2, 0), &Data);
if (status != 0){
ErrorHandler
(
"エラー: WSAStartupの実行が失敗しました。",
GetLastError()
);
}
// SCMに登録する。
success =
StartServiceCtrlDispatcher(serviceTable);
if (!success)
ErrorHandler("StartServiceCtrlDispatcherでエラーが発生",
GetLastError());
}
/*****************************************************************************/
int sock_addr_ini
(
struct sockaddr_in *addr_tmp
,unsigned long ip_addr
,unsigned short port
)
{
// sockaddr_in構造体への代入
// アドレスのポート部分を指定する。
addr_tmp->sin_port = port;
// アドレスファミリをインターネットとして指定する。
addr_tmp->sin_family = AF_INET;
// アドレスを指定する。
addr_tmp->sin_addr.s_addr = ip_addr;
return(0);
}
/*****************************************************************************/
int socket_close( SOCKET socket_num )
{
int status; //ステータス
status = shutdown(socket_num,2);
if (status == SOCKET_ERROR){
cerr << "エラー: socketのshutdown実行が失敗しました。"<< endl;
return(status);
}
status = closesocket(socket_num);
if (status == SOCKET_ERROR){
cerr << "エラー: closesocketの実行が失敗しました。"<< endl;
}
return(status);
}
/*****************************************************************************/
int recv_with_term(SOCKET soc,unsigned char term_char,void *recv_buff){
int point = 0;
int retval;
while(1){
retval = recv
(
soc,
(char *)recv_buff+point,
1,
0
);
//printf("%c",*( (unsigned char *)recv_buff+point ));
if( *( (unsigned char *)recv_buff+point ) == term_char ){
break;
}
point++;
}
return(0);
}
/*****************************************************************************/
int send_with_term(SOCKET soc,unsigned char term_char,void *send_buff){
int point = 0;
int retval;
while(1){
retval = send
(
soc,
(const char *)send_buff+point,
1,
0
);
//printf("%c",*( (unsigned char *)recv_buff+point ));
if( *( (unsigned char *)send_buff+point ) == term_char ){
break;
}
point++;
}
return(0);
}
/********************************************************************* ***/
unsigned long send_loop
(
SOCKET soc, // ソケット記述子
void *buff, // 送信バッファ
unsigned int len // 送信したいバイト数
)
{
unsigned long sum = 0;
int retval = 0;
unsigned long tmp_len;
unsigned long MaxBuffSize = 32000; // MAX:32767
do
{
tmp_len = len - sum;
if( tmp_len>MaxBuffSize )
{
tmp_len = MaxBuffSize;
}
retval = send
(
soc,
((char *)buff)+sum,
tmp_len,
0
);
if( (retval != -1) && (retval > 0) )
{
sum += retval;
}
} while( (retval != -1) && (retval > 0) && (sum < len) );
if( sum == len )
{
return sum;
}
else
{
return (-1);
}
}
|