1/*******************************************************************************
2 * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 *  - Redistributions of source code must retain the above copyright notice,
8 *    this list of conditions and the following disclaimer.
9 *
10 *  - Redistributions in binary form must reproduce the above copyright notice,
11 *    this list of conditions and the following disclaimer in the documentation
12 *    and/or other materials provided with the distribution.
13 *
14 *  - Neither the name of Intel Corp. nor the names of its
15 *    contributors may be used to endorse or promote products derived from this
16 *    software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30
31#ifndef __LME_CONNECTION_H__
32#define __LME_CONNECTION_H__
33
34#if defined(__sun) || defined(_LINUX)
35#include "HECIUnix.h"
36#else
37#include "HECIWin.h"
38#endif
39
40#include <map>
41#include <string>
42#include "LMS_if.h"
43#include "Thread.h"
44#include "Semaphore.h"
45#include "Event.h"
46#include "ATNetworkTool.h"
47
48
49struct AuthMethodData {
50};
51
52struct AuthPasswordData : AuthMethodData {
53	std::string Password;
54};
55
56struct LMEMessage {
57
58	LMEMessage(APF_MESSAGE_TYPE type) :
59		MessageType(type) {}
60
61	const APF_MESSAGE_TYPE MessageType;
62};
63
64struct LMEDisconnectMessage : LMEMessage {
65
66	LMEDisconnectMessage(APF_DISCONNECT_REASON_CODE reasonCode) :
67		LMEMessage(APF_DISCONNECT),
68		ReasonCode(reasonCode) {}
69
70	APF_DISCONNECT_REASON_CODE ReasonCode;
71};
72
73struct LMEServiceRequestMessage : LMEMessage {
74
75	LMEServiceRequestMessage(std::string serviceName = "") :
76		LMEMessage(APF_SERVICE_REQUEST),
77		ServiceName(serviceName) {}
78
79	std::string ServiceName;
80};
81
82struct LMEGlobalRequestMessage : LMEMessage {
83
84	enum REQUEST_TYPE {
85		TCP_FORWARD_REQUEST,
86		TCP_FORWARD_CANCEL_REQUEST,
87		UDP_SEND_TO
88	};
89
90	LMEGlobalRequestMessage(REQUEST_TYPE type) :
91		LMEMessage(APF_GLOBAL_REQUEST),
92		RequestType(type) {}
93
94	const REQUEST_TYPE RequestType;
95};
96
97struct LMEProtocolVersionMessage : LMEMessage {
98
99	LMEProtocolVersionMessage(UINT32 majorVersion = 0,
100				  UINT32 minorVersion = 0,
101				  APF_TRIGGER_REASON triggerReason = LME_REQUEST) :
102		LMEMessage(APF_PROTOCOLVERSION),
103		MajorVersion(majorVersion),
104		MinorVersion(minorVersion),
105		TriggerReason(triggerReason) {}
106
107	UINT32 MajorVersion;
108	UINT32 MinorVersion;
109	APF_TRIGGER_REASON TriggerReason;
110
111	struct LMEProtocolVersionMessage &operator=(const struct LMEProtocolVersionMessage &y)
112	{
113		if (this != &y) {
114			this->MajorVersion = y.MajorVersion;
115			this->MinorVersion = y.MinorVersion;
116		}
117		return *this;
118	};
119	bool operator<(const struct LMEProtocolVersionMessage &y) const
120	{
121		if (this->MajorVersion != y.MajorVersion) {
122			return (this->MajorVersion < y.MajorVersion);
123		}
124		return (this->MinorVersion < y.MinorVersion);
125	}
126	bool operator>(const struct LMEProtocolVersionMessage &y) const
127	{
128		if (this->MajorVersion != y.MajorVersion) {
129			return (this->MajorVersion > y.MajorVersion);
130		}
131		return (this->MinorVersion > y.MinorVersion);
132	}
133};
134
135struct LMEUserAuthRequestMessage : LMEMessage {
136
137	LMEUserAuthRequestMessage(std::string username = "",
138				  std::string serviceName = "",
139				  std::string methodName = "",
140				  AuthMethodData *methodData = NULL) :
141		LMEMessage(APF_USERAUTH_REQUEST),
142		Username(username),
143		ServiceName(ServiceName),
144		MethodName(methodName),
145		MethodData(methodData) {}
146
147	std::string Username;
148	std::string ServiceName;
149	std::string MethodName;
150
151	AuthMethodData *MethodData;
152};
153
154
155struct LMETcpForwardRequestMessage : LMEGlobalRequestMessage {
156
157	LMETcpForwardRequestMessage(std::string address = "", UINT32 port = 0) :
158		LMEGlobalRequestMessage(TCP_FORWARD_REQUEST),
159		Address(address),
160		Port(port) {}
161
162	std::string Address;
163	UINT32 Port;
164};
165
166struct LMETcpForwardCancelRequestMessage : LMEGlobalRequestMessage {
167
168	LMETcpForwardCancelRequestMessage(std::string address = "", UINT32 port = 0) :
169		LMEGlobalRequestMessage(TCP_FORWARD_CANCEL_REQUEST),
170		Address(address),
171		Port(port) {}
172
173	std::string Address;
174	UINT32 Port;
175};
176
177struct LMEUdpSendToMessage : LMEGlobalRequestMessage {
178
179	LMEUdpSendToMessage(std::string address = "", UINT32 port = 0,
180			    UINT32 dataLength = 0, UINT8 *data = NULL) :
181		LMEGlobalRequestMessage(UDP_SEND_TO),
182		Address(address),
183		Port(port),
184		DataLength(dataLength)
185	{
186		if ((data != NULL) && (dataLength != 0)) {
187			Data = new UINT8[dataLength];
188			memcpy(Data, data, dataLength);
189		} else {
190			Data = NULL;
191		}
192
193	}
194
195	~LMEUdpSendToMessage()
196	{
197		if (Data != NULL) {
198			delete[] Data;
199			Data = NULL;
200		}
201	}
202
203	std::string Address;
204	UINT32 Port;
205	UINT32 DataLength;
206	UINT8 *Data;
207};
208
209struct LMEChannelOpenRequestMessage : LMEMessage {
210
211	enum CHANNEL_TYPE {
212		FORWARDED,
213		DIRECT
214	};
215
216	LMEChannelOpenRequestMessage(CHANNEL_TYPE channelType = FORWARDED,
217				     UINT32 senderChannel = 0,
218				     UINT32 initialWindow = 0,
219				     std::string address = "", UINT32 port = 0) :
220		LMEMessage(APF_CHANNEL_OPEN),
221		ChannelType(channelType),
222		SenderChannel(senderChannel),
223		InitialWindow(initialWindow),
224		Address(address),
225		Port(port) {}
226
227	CHANNEL_TYPE ChannelType;
228	UINT32 SenderChannel;
229	UINT32 InitialWindow;
230	std::string Address;
231	UINT32 Port;
232};
233
234struct LMEChannelOpenReplaySuccessMessage : LMEMessage {
235
236	LMEChannelOpenReplaySuccessMessage(UINT32 recipientChannel = 0,
237					   UINT32 senderChannel = 0,
238					   UINT32 initialWindow = 0) :
239		LMEMessage(APF_CHANNEL_OPEN_CONFIRMATION),
240		RecipientChannel(recipientChannel),
241		SenderChannel(senderChannel),
242		InitialWindow(initialWindow) {}
243
244	UINT32 RecipientChannel;
245	UINT32 SenderChannel;
246	UINT32 InitialWindow;
247};
248
249struct LMEChannelOpenReplayFailureMessage : LMEMessage {
250
251	LMEChannelOpenReplayFailureMessage(UINT32 recipientChannel = 0,
252	    OPEN_FAILURE_REASON reasonCode = OPEN_FAILURE_REASON_ADMINISTRATIVELY_PROHIBITED) :
253		LMEMessage(APF_CHANNEL_OPEN_FAILURE),
254		RecipientChannel(recipientChannel),
255		ReasonCode(reasonCode) {}
256
257	UINT32 RecipientChannel;
258	OPEN_FAILURE_REASON ReasonCode;
259};
260
261struct LMEChannelCloseMessage : LMEMessage {
262
263	LMEChannelCloseMessage(UINT32 recipientChannel = 0) :
264		LMEMessage(APF_CHANNEL_CLOSE),
265		RecipientChannel(recipientChannel) {}
266
267	UINT32 RecipientChannel;
268};
269
270struct LMEChannelDataMessage : LMEMessage {
271
272	LMEChannelDataMessage(UINT32 recipientChannel = 0,
273			      UINT32 dataLength = 0,
274			      UINT8 *data = NULL) :
275		LMEMessage(APF_CHANNEL_DATA),
276		RecipientChannel(recipientChannel),
277		DataLength(dataLength)
278	{
279		if ((data != NULL) && (dataLength != 0)) {
280			Data = new UINT8[dataLength];
281			memcpy(Data, data, dataLength);
282		} else {
283			Data = NULL;
284		}
285	}
286
287	~LMEChannelDataMessage()
288	{
289		if (Data != NULL) {
290			delete[] Data;
291			Data = NULL;
292		}
293	}
294
295	const UINT32 RecipientChannel;
296	const UINT32 DataLength;
297	UINT8 *Data;
298};
299
300struct LMEChannelWindowAdjustMessage : LMEMessage {
301
302	LMEChannelWindowAdjustMessage(UINT32 recipientChannel = 0,
303				      UINT32 bytesToAdd = 0) :
304		LMEMessage(APF_CHANNEL_WINDOW_ADJUST),
305		RecipientChannel(recipientChannel),
306		BytesToAdd(bytesToAdd) {}
307
308	UINT32 RecipientChannel;
309	UINT32 BytesToAdd;
310};
311
312typedef void (*HECICallback)(void *param, void *buffer, unsigned int len, int *status);
313
314class LMEConnection
315{
316public:
317	LMEConnection(bool verbose = false);
318	~LMEConnection();
319
320	bool Init(HECICallback cb, void *param);
321	bool IsInitialized();
322	bool Disconnect(APF_DISCONNECT_REASON_CODE reasonCode);
323	bool ServiceAccept(std::string serviceName);
324	bool UserAuthSuccess();
325	bool ProtocolVersion(const LMEProtocolVersionMessage versionMessage);
326	bool TcpForwardReplySuccess(UINT32 port);
327	bool TcpForwardReplyFailure();
328	bool TcpForwardCancelReplySuccess();
329	bool TcpForwardCancelReplyFailure();
330	bool ChannelOpenForwardedRequest(UINT32 sender, UINT32 connectedPort,
331					 std::string originatorIP, UINT32 originatorPort);
332	bool ChannelOpenReplaySuccess(UINT32 recipient, UINT32 sender);
333	bool ChannelOpenReplayFailure(UINT32 recipient, UINT32 reason);
334	bool ChannelClose(UINT32 recipient);
335	int  ChannelData(UINT32 recipient, UINT32 len, unsigned char *buffer);
336	bool ChannelWindowAdjust(UINT32 recipient, UINT32 len);
337
338	//BACKWARD COMPATIBLE PUBLIC - BEGIN
339	bool CompatProtocolVersion();
340	bool CompatRequestIPFQDN();
341	bool CompatOpenConnection(in_port_t mePort, ATAddress addr, unsigned int &connID);
342	int  CompatSendMessage(UINT8 connID, UINT32 len, unsigned char *buffer);
343	void CompatCloseConnection(int connID, int status);
344	//BACKWARD COMPATIBLE PUBLIC - END
345
346	void Deinit();
347	unsigned int GetHeciBufferSize() const;
348
349	enum INIT_STATES {
350		INIT_STATE_DISCONNECTED = 0,
351		INIT_STATE_CONNECTING,
352		INIT_STATE_CONNECTED
353	};
354
355	static const UINT32 RX_WINDOW_SIZE;
356
357	unsigned char protocolVer;
358
359private:
360	static const GUID _guid;
361
362	static void _rxThreadFunc(void *param);
363
364	void _doRX();
365	int _receiveMessage(unsigned char *buffer, int len);
366	int _sendMessage(unsigned char *buffer, int len);
367	bool _checkMinMsgSize(unsigned char *buf, unsigned int bytesRead);
368	void _apfGlobalRequest(unsigned char *rxBuffer, unsigned int bytesRead, int *status);
369	void _apfUserAuthRequest(unsigned char *rxBuffer, unsigned int bytesRead, int *status);
370	void _apfChannelOpen(unsigned char *rxBuffer, unsigned int bytesRead, int *status);
371	void _apfChannelOpenDirect(unsigned char *rxBuffer, unsigned int bytesRead, UINT32 *senderChannel, int *status);
372
373
374	unsigned char _reqID;
375	unsigned char *_txBuffer;
376	Thread *_rxThread;
377	HECICallback _cb;
378	void *_cbParam;
379	Semaphore _initLock;
380	Semaphore _sendMessageLock;
381	INIT_STATES _initState;
382	Event _threadStartedEvent;
383#if defined(__sun) || defined(_LINUX)
384	HECILinux _heci;
385#else
386	HECIWin _heci;
387#endif
388
389	//BACKWARD COMPATIBLE PRIVATE - BEGIN
390	static const GUID _guidCompat;
391
392	void _doRXCompat();
393
394	struct CompatConnection {
395		Event *event;
396		int connID;
397		UINT8 status;
398	};
399	typedef std::map<int, CompatConnection> CompatConnMap;
400	CompatConnMap _compatPendingConnections;
401	Semaphore _compatMapLock;
402#if defined(__sun) || defined(_LINUX)
403	HECILinux _heciCompat;
404#else
405	HECIWin _heciCompat;
406#endif
407	//BACKWARD COMPATIBLE PRIVATE - END
408
409	HECI *_pHeci;
410};
411
412#endif
413