-
Notifications
You must be signed in to change notification settings - Fork 0
/
selproto.c
200 lines (192 loc) · 4.87 KB
/
selproto.c
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//
// SELPROTO.C -- SelectProtocols()関数
//
#include <winsock2.h>
////////////////////////////////////////////////////////////
// int SelectProtocols(
// DWORD dwSetFlags,
// DWORD dwNotSetFlags,
// LPWSAPROTOCOL_INFO lpProtocolBuffer,
// LPDWORD lpdwBufferLength
// )
//
// Retrieves information about available transport protocols
// that meet the criteria indicated by dwSetFlags and
// dwNotSetFlags
//
// PARAMETERS
//
// dwSetFlags A bitmask of values to ensure
// are set in the protocol's
// WSAPROTOCOL_INFO.dwServiceFlags1
// field.
//
// dwNotSetFlags A bitmask of values to ensure
// are NOT set in the protocol's
// WSAPROTOCOL_INFO.dwServiceFlags1
// field.
//
// lpProtocolBuffer The buffer to be filled with
// WSAPROTOCOL_INFO structures.
//
// lpdwBufferLength On input, the size in bytes of
// the buffer pointed to by the
// lpProtocolBuffer parameter.
// On ouput, the minimum size the
// buffer must be to retrieve all
// of the requested information.
//
// REMARKS
//
// SelectProtocols() fills the supplied buffer with
// WSAPROTOCOL_INFO structures for all protocols where the
// flags specified in dwSetFlags are set and all flags in
// dwNotSetFlags are NOT set.
//
// Example: To retrieve information about all installed
// protocols that are connection-oriented and reliable,
// call SelectProtocols() like this:
//
// nRet = SelectProtocols(XP1_GUARANTEED_DELIVERY|XP1_GUARANTEED_ORDER,
// XP1_CONNECTIONLESS,
// lpProtocolBuffer,
// &dwBufLen);
//
// In this example, SelectProtocols() will return information
// about all installed protocols and protocol chains that
// have the XP1_GUARANTEED_DELIVERY and XP1_GUARANTEED_ORDER
// flags set and that also don't have XP1_CONNECTIONLESS set.
//
// RETURN VALUES
//
// If no error occurs, SelectProtocols() returns the number of
// WSAPROTOCOL_INFO structure copied to the supplied buffer.
// If an error occurs, it returns SOCKET_ERROR and a specific
// error code can be found with WSAGetLastError();
//
int SelectProtocols(
DWORD dwSetFlags,
DWORD dwNotSetFlags,
LPWSAPROTOCOL_INFO lpProtocolBuffer,
LPDWORD lpdwBufferLength
)
{
LPBYTE pBuf;
LPWSAPROTOCOL_INFO pInfo;
DWORD dwNeededLen;
LPWSAPROTOCOL_INFO pRetInfo;
DWORD dwRetLen;
int nCount;
int nMatchCount;
int nRet;
//
// 必要なバッファサイズを調べる
dwNeededLen = 0;
nRet = WSAEnumProtocols(NULL, NULL, &dwNeededLen);
if (nRet == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAENOBUFS)
return SOCKET_ERROR;
}
//
// バッファを割り当てる
//
pBuf = malloc(dwNeededLen);
if (pBuf == NULL)
{
WSASetLastError(WSAENOBUFS);
return SOCKET_ERROR;
}
//
// 実際の呼び出しを行う
//
nRet = WSAEnumProtocols(NULL,
(LPWSAPROTOCOL_INFO)pBuf,
&dwNeededLen);
if (nRet == SOCKET_ERROR)
{
free(pBuf);
return SOCKET_ERROR;
}
//
// プロトコルを選択するためのヘルパーマクロ
//
#define REJECTSET(f) \
((dwSetFlags & f) && !(pInfo->dwServiceFlags1 & f))
#define REJECTNOTSET(f) \
((dwNotSetFlags &f) && (pInfo->dwServiceFlags1 & f))
#define REJECTEDBY(f) (REJECTSET(f) || REJECTNOTSET(f))
//
// ループ処理で各プロトコルを選択する
//
pInfo = (LPWSAPROTOCOL_INFO)pBuf;
pRetInfo = lpProtocolBuffer;
dwRetLen = 0;
nMatchCount = 0;
for(nCount = 0; nCount < nRet; nCount++)
{
//
// 要求されたすべてのフラグをチェックする
//
while(1)
{
if (REJECTEDBY(XP1_CONNECTIONLESS))
break;
if (REJECTEDBY(XP1_GUARANTEED_DELIVERY))
break;
if (REJECTEDBY(XP1_GUARANTEED_ORDER))
break;
if (REJECTEDBY(XP1_MESSAGE_ORIENTED))
break;
if (REJECTEDBY(XP1_PSEUDO_STREAM))
break;
if (REJECTEDBY(XP1_GRACEFUL_CLOSE))
break;
if (REJECTEDBY(XP1_EXPEDITED_DATA))
break;
if (REJECTEDBY(XP1_CONNECT_DATA))
break;
if (REJECTEDBY(XP1_DISCONNECT_DATA))
break;
if (REJECTEDBY(XP1_SUPPORT_BROADCAST))
break;
if (REJECTEDBY(XP1_SUPPORT_MULTIPOINT))
break;
if (REJECTEDBY(XP1_MULTIPOINT_DATA_PLANE))
break;
if (REJECTEDBY(XP1_QOS_SUPPORTED))
break;
if (REJECTEDBY(XP1_UNI_SEND))
break;
if (REJECTEDBY(XP1_UNI_RECV))
break;
if (REJECTEDBY(XP1_IFS_HANDLES))
break;
if (REJECTEDBY(XP1_PARTIAL_MESSAGE))
break;
//
// ここまで来た場合は、
// プロトコルはすべての要件を満たしている
//
dwRetLen += sizeof(WSAPROTOCOL_INFO);
if (dwRetLen > *lpdwBufferLength)
{
// 指定のバッファが小さすぎる
WSASetLastError(WSAENOBUFS);
*lpdwBufferLength = dwNeededLen;
free(pBuf);
return SOCKET_ERROR;
}
nMatchCount++;
// このプロトコルを呼び出し元のバッファにコピーする
memcpy(pRetInfo, pInfo, sizeof(WSAPROTOCOL_INFO));
pRetInfo++;
break;
}
pInfo++;
}
free(pBuf);
*lpdwBufferLength = dwRetLen;
return(nMatchCount);
}
////////////////////////////////////////////////////////////