netdirect: add winverbs ND provider
[mirror/winof/.git] / ulp / netdirect / user / nd_connect.cpp
1 /*\r
2  * Copyright (c) 2009 Intel Corporation. All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  */\r
29 \r
30 #include "nd_connect.h"\r
31 #include "nd_ep.h"\r
32 \r
33 \r
34 CNDConnector::CNDConnector(CNDAdapter *pAdapter)\r
35 {\r
36         pAdapter->AddRef();\r
37         m_pAdapter = pAdapter;\r
38         m_pWvConnEp = NULL;\r
39 }\r
40 \r
41 STDMETHODIMP CNDConnector::\r
42 Init(void)\r
43 {\r
44         return m_pAdapter->m_pWvProvider->CreateConnectEndpoint(&m_pWvConnEp);\r
45 }\r
46 \r
47 CNDConnector::~CNDConnector()\r
48 {\r
49         if (m_pWvConnEp != NULL) {\r
50                 m_pWvConnEp->Release();\r
51         }\r
52         m_pAdapter->Release();\r
53 }\r
54 \r
55 STDMETHODIMP CNDConnector::\r
56 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
57 {\r
58         if (riid != IID_IUnknown && riid != IID_INDConnector) {\r
59                 *ppvObj = NULL;\r
60                 return E_NOINTERFACE;\r
61         }\r
62 \r
63         *ppvObj = this;\r
64         AddRef();\r
65         return ND_SUCCESS;\r
66 }\r
67 \r
68 STDMETHODIMP_(ULONG) CNDConnector::\r
69 AddRef(void)\r
70 {\r
71         return CNDBase::AddRef();\r
72 }\r
73 \r
74 STDMETHODIMP_(ULONG) CNDConnector::\r
75 Release(void)\r
76 {\r
77         return CNDBase::Release();\r
78 }\r
79 \r
80 STDMETHODIMP CNDConnector::\r
81 CancelOverlappedRequests(void)\r
82 {\r
83         return m_pWvConnEp->CancelOverlappedRequests();\r
84 }\r
85 \r
86 STDMETHODIMP CNDConnector::\r
87 GetOverlappedResult(OVERLAPPED *pOverlapped,\r
88                                         SIZE_T *pNumberOfBytesTransferred, BOOL bWait)\r
89 {\r
90         return m_pWvConnEp->GetOverlappedResult(pOverlapped,\r
91                                                                                         (DWORD *) pNumberOfBytesTransferred,\r
92                                                                                         bWait);\r
93 }\r
94 \r
95 STDMETHODIMP CNDConnector::\r
96 CreateEndpoint(INDCompletionQueue* pInboundCq, INDCompletionQueue* pOutboundCq,\r
97                            SIZE_T nInboundEntries, SIZE_T nOutboundEntries,\r
98                            SIZE_T nInboundSge, SIZE_T nOutboundSge,\r
99                            SIZE_T InboundReadLimit, SIZE_T OutboundReadLimit,\r
100                            SIZE_T* pMaxInlineData, INDEndpoint** ppEndpoint)\r
101 {\r
102         CNDCompletionQueue *incq = (CNDCompletionQueue *) pInboundCq;\r
103         CNDCompletionQueue *outcq = (CNDCompletionQueue *) pOutboundCq;\r
104 \r
105         return CNDEndpoint::CreateInstance(this, incq, outcq,\r
106                                                                            nInboundEntries, nOutboundEntries,\r
107                                                                            nInboundSge, nOutboundSge,\r
108                                                                            InboundReadLimit, OutboundReadLimit,\r
109                                                                            pMaxInlineData, ppEndpoint);\r
110 }\r
111 \r
112 STDMETHODIMP CNDConnector::\r
113 Connect(INDEndpoint* pEndpoint,\r
114                 const struct sockaddr* pAddress, SIZE_T AddressLength,\r
115                 INT Protocol, USHORT LocalPort,\r
116                 const void* pPrivateData, SIZE_T PrivateDataLength,\r
117                 OVERLAPPED* pOverlapped)\r
118 {\r
119         CNDEndpoint                     *ep = (CNDEndpoint *) pEndpoint;\r
120         WV_SOCKADDR                     addr;\r
121         WV_CONNECT_PARAM        attr;\r
122 \r
123         RtlCopyMemory(&addr, pAddress, AddressLength);\r
124         if (addr.Sa.sa_family == AF_INET) {\r
125                 addr.Sin.sin_port = LocalPort;\r
126         } else {\r
127                 addr.Sin6.sin6_port = LocalPort;\r
128         }\r
129 \r
130         RtlZeroMemory(&attr, sizeof attr);\r
131         if ((attr.DataLength = PrivateDataLength)) {\r
132                 RtlCopyMemory(attr.Data, pPrivateData, PrivateDataLength);\r
133         }\r
134         attr.ResponderResources = ep->m_ResponderResources;\r
135         attr.InitiatorDepth = ep->m_InitiatorDepth;\r
136         attr.RetryCount = 7;\r
137 \r
138         return m_pWvConnEp->Connect(ep->m_pWvQp, &addr.Sa, &attr, pOverlapped);\r
139 }\r
140 \r
141 STDMETHODIMP CNDConnector::\r
142 CompleteConnect(OVERLAPPED* pOverlapped)\r
143 {\r
144         WV_CONNECT_PARAM        attr;\r
145 \r
146         RtlZeroMemory(&attr, sizeof attr);\r
147         return m_pWvConnEp->Accept(NULL, &attr, pOverlapped);\r
148 }\r
149 \r
150 STDMETHODIMP CNDConnector::\r
151 Accept(INDEndpoint* pEndpoint,\r
152            const void* pPrivateData, SIZE_T PrivateDataLength,\r
153            OVERLAPPED* pOverlapped)\r
154 {\r
155         CNDEndpoint                     *ep = (CNDEndpoint *) pEndpoint;\r
156         WV_CONNECT_PARAM        attr;\r
157 \r
158         RtlZeroMemory(&attr, sizeof attr);\r
159         if ((attr.DataLength = PrivateDataLength)) {\r
160                 RtlCopyMemory(attr.Data, pPrivateData, PrivateDataLength);\r
161         }\r
162         attr.ResponderResources = ep->m_ResponderResources;\r
163         attr.InitiatorDepth = ep->m_InitiatorDepth;\r
164 \r
165         return m_pWvConnEp->Accept(ep->m_pWvQp, &attr, pOverlapped);\r
166 }\r
167 \r
168 STDMETHODIMP CNDConnector::\r
169 Reject(const void* pPrivateData, SIZE_T PrivateDataLength)\r
170 {\r
171         return m_pWvConnEp->Reject(pPrivateData, PrivateDataLength);\r
172 }\r
173 \r
174 STDMETHODIMP CNDConnector::\r
175 GetConnectionData(SIZE_T* pInboundReadLimit, SIZE_T* pOutboundReadLimit,\r
176                                   void* pPrivateData, SIZE_T* pPrivateDataLength)\r
177 {\r
178         WV_CONNECT_ATTRIBUTES attr;\r
179         HRESULT hr;\r
180         \r
181         if (pPrivateDataLength && *pPrivateDataLength < ND_PRIVATE_DATA_SIZE) {\r
182                 *pPrivateDataLength = ND_PRIVATE_DATA_SIZE;\r
183                 return ND_BUFFER_OVERFLOW;\r
184         }\r
185 \r
186         hr = m_pWvConnEp->Query(&attr);\r
187         if (FAILED(hr)) {\r
188                 return hr;\r
189         }\r
190 \r
191         *pInboundReadLimit = attr.Param.ResponderResources;\r
192         *pOutboundReadLimit = attr.Param.InitiatorDepth;\r
193         if (pPrivateDataLength) {\r
194                 RtlCopyMemory(pPrivateData, attr.Param.Data, ND_PRIVATE_DATA_SIZE);\r
195                 *pPrivateDataLength = ND_PRIVATE_DATA_SIZE;\r
196         }\r
197         return ND_SUCCESS;\r
198 }\r
199 \r
200 static SIZE_T GetAddressSize(WV_SOCKADDR *addr)\r
201 {\r
202         return (addr->Sa.sa_family == AF_INET) ? sizeof(addr->Sin) : sizeof(addr->Sin6);\r
203 }\r
204 \r
205 STDMETHODIMP CNDConnector::\r
206 GetLocalAddress(struct sockaddr* pAddress, SIZE_T* pAddressLength)\r
207 {\r
208         WV_CONNECT_ATTRIBUTES attr;\r
209         HRESULT hr;\r
210         \r
211         hr = m_pWvConnEp->Query(&attr);\r
212         if (FAILED(hr)) {\r
213                 return hr;\r
214         }\r
215 \r
216         if (*pAddressLength < GetAddressSize(&attr.LocalAddress)) {\r
217                 hr = ND_BUFFER_OVERFLOW;\r
218                 goto out;\r
219         }\r
220 \r
221         RtlCopyMemory(pAddress, &attr.LocalAddress, GetAddressSize(&attr.LocalAddress));\r
222 out:\r
223         *pAddressLength = GetAddressSize(&attr.LocalAddress);\r
224         return hr;\r
225 }\r
226 \r
227 STDMETHODIMP CNDConnector::\r
228 GetPeerAddress(struct sockaddr* pAddress, SIZE_T* pAddressLength)\r
229 {\r
230         WV_CONNECT_ATTRIBUTES attr;\r
231         HRESULT hr;\r
232         \r
233         hr = m_pWvConnEp->Query(&attr);\r
234         if (FAILED(hr)) {\r
235                 return hr;\r
236         }\r
237 \r
238         if (*pAddressLength < GetAddressSize(&attr.PeerAddress)) {\r
239                 hr = ND_BUFFER_OVERFLOW;\r
240                 goto out;\r
241         }\r
242 \r
243         RtlCopyMemory(pAddress, &attr.PeerAddress, GetAddressSize(&attr.PeerAddress));\r
244 out:\r
245         *pAddressLength = GetAddressSize(&attr.PeerAddress);\r
246         return hr;\r
247 }\r
248 \r
249 STDMETHODIMP CNDConnector::\r
250 NotifyDisconnect(OVERLAPPED* pOverlapped)\r
251 {\r
252         return m_pWvConnEp->NotifyDisconnect(pOverlapped);\r
253 }\r
254 \r
255 STDMETHODIMP CNDConnector::\r
256 Disconnect(OVERLAPPED* pOverlapped)\r
257 {\r
258         return m_pWvConnEp->Disconnect(pOverlapped);\r
259 }\r