-
Notifications
You must be signed in to change notification settings - Fork 14
/
RPCServer.cpp
160 lines (142 loc) · 3.92 KB
/
RPCServer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "RPCServer.h"
#include "ServerSocket.h"
#include <stdio.h>
#define MIN_PROG_NUM 100000
enum
{
CALL = 0,
REPLY = 1
};
enum
{
MSG_ACCEPTED = 0,
MSG_DENIED = 1
};
enum
{
SUCCESS = 0,
PROG_UNAVAIL = 1,
PROG_MISMATCH = 2,
PROC_UNAVAIL = 3,
GARBAGE_ARGS = 4
};
typedef struct
{
unsigned long flavor;
unsigned long length;
} OPAQUE_AUTH;
typedef struct
{
unsigned long header;
unsigned long XID;
unsigned long msg;
unsigned long rpcvers;
unsigned long prog;
unsigned long vers;
unsigned long proc;
OPAQUE_AUTH cred;
OPAQUE_AUTH verf;
} RPC_HEADER;
CRPCServer::CRPCServer()
{
int i;
for (i = 0; i < PROG_NUM; i++)
m_pProgTable[i] = NULL;
m_hMutex = CreateMutex(NULL, false, NULL);
}
CRPCServer::~CRPCServer()
{
CloseHandle(m_hMutex);
}
void CRPCServer::Set(int nProg, CRPCProg *pRPCProg)
{
m_pProgTable[nProg - MIN_PROG_NUM] = pRPCProg; //set program handler
}
void CRPCServer::SetLogOn(bool bLogOn)
{
int i;
for (i = 0; i < PROG_NUM; i++)
if (m_pProgTable[i] != NULL)
m_pProgTable[i]->SetLogOn(bLogOn);
}
void CRPCServer::SocketReceived(CSocket *pSocket)
{
IInputStream *pInStream;
int nResult;
WaitForSingleObject(m_hMutex, INFINITE);
pInStream = pSocket->GetInputStream();
while (pInStream->GetSize() > 0)
{
nResult = Process(pSocket->GetType(), pInStream, pSocket->GetOutputStream(), pSocket->GetRemoteAddress()); //process input data
pSocket->Send(); //send response
if (nResult != PRC_OK || pSocket->GetType() == SOCK_DGRAM)
break;
}
ReleaseMutex(m_hMutex);
}
int CRPCServer::Process(int nType, IInputStream *pInStream, IOutputStream *pOutStream, char *pRemoteAddr)
{
RPC_HEADER header;
int nPos, nSize;
ProcessParam param;
int nResult;
nResult = PRC_OK;
if (nType == SOCK_STREAM)
pInStream->Read(&header.header);
pInStream->Read(&header.XID);
pInStream->Read(&header.msg);
pInStream->Read(&header.rpcvers); //rpc version
pInStream->Read(&header.prog); //program
pInStream->Read(&header.vers); //program version
pInStream->Read(&header.proc); //procedure
pInStream->Read(&header.cred.flavor);
pInStream->Read(&header.cred.length);
pInStream->Skip(header.cred.length);
pInStream->Read(&header.verf.flavor); //vefifier
if (pInStream->Read(&header.verf.length) < sizeof(header.verf.length))
nResult = PRC_FAIL;
if (pInStream->Skip(header.verf.length) < header.verf.length)
nResult = PRC_FAIL;
if (nType == SOCK_STREAM)
{
nPos = pOutStream->GetPosition(); //remember current position
pOutStream->Write(header.header); //this value will be updated later
}
pOutStream->Write(header.XID);
pOutStream->Write(REPLY);
pOutStream->Write(MSG_ACCEPTED);
pOutStream->Write(header.verf.flavor);
pOutStream->Write(header.verf.length);
if (nResult == PRC_FAIL) //input data is truncated
pOutStream->Write(GARBAGE_ARGS);
else if (header.prog < MIN_PROG_NUM || header.prog >= MIN_PROG_NUM + PROG_NUM) //program is unavailable
pOutStream->Write(PROG_UNAVAIL);
else if (m_pProgTable[header.prog - MIN_PROG_NUM] == NULL) //program is unavailable
pOutStream->Write(PROG_UNAVAIL);
else
{
pOutStream->Write(SUCCESS); //this value may be modified later if process failed
param.nVersion = header.vers;
param.nProc = header.proc;
param.pRemoteAddr = pRemoteAddr;
nResult = m_pProgTable[header.prog - MIN_PROG_NUM]->Process(pInStream, pOutStream, ¶m); //process rest input data by program
if (nResult == PRC_NOTIMP) //procedure is not implemented
{
pOutStream->Seek(-4, SEEK_CUR);
pOutStream->Write(PROC_UNAVAIL);
}
else if (nResult == PRC_FAIL) //input data is truncated
{
pOutStream->Seek(-4, SEEK_CUR);
pOutStream->Write(GARBAGE_ARGS);
}
}
if (nType == SOCK_STREAM)
{
nSize = pOutStream->GetPosition(); //remember current position
pOutStream->Seek(nPos, SEEK_SET); //seek to the position of head
header.header = 0x80000000 + nSize - nPos - 4; //size of output data
pOutStream->Write(header.header); //update header
}
return nResult;
}