xref: /titanic_41/usr/src/cmd/lms/LMEConnection.cpp (revision 657a8c206b913d1ee578fd725f0b25eca5b77253)
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 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 #include <cerrno>
35 #include "types.h"
36 #include "LMEConnection.h"
37 #include "LMS_if.h"
38 #include "Lock.h"
39 #include "glue.h"
40 
41 #if defined(__sun) || defined(_LINUX)
42 #include <netinet/in.h>
43 #define _strnicmp strncasecmp
44 #endif	// __sun || _LINUX
45 
46 #define HECI_IO_TIMEOUT 5000
47 
48 extern glue plugin;
49 
50 const GUID LMEConnection::_guid = {0x6733a4db, 0x0476, 0x4e7b, {0xb3, 0xaf, 0xbc, 0xfc, 0x29, 0xbe, 0xe7, 0xa7}};
51 
52 const UINT32 LMEConnection::RX_WINDOW_SIZE = 1024;
53 
54 LMEConnection::LMEConnection(bool verbose) :
55 _reqID(0),
56 _txBuffer(NULL),
57 _rxThread(NULL),
58 _cb(NULL),
59 _cbParam(NULL),
60 _initState(INIT_STATE_DISCONNECTED),
61 _heci(_guid, verbose),
62 _heciCompat(_guidCompat, verbose),
63 _pHeci(NULL)
64 {
65 }
66 
67 LMEConnection::~LMEConnection()
68 {
69 }
70 
71 bool LMEConnection::IsInitialized()
72 {
73 	Lock il(_initLock);
74 	return ((_initState == INIT_STATE_CONNECTED) ? true : false);
75 }
76 
77 bool LMEConnection::Init(HECICallback cb, void *param)
78 {
79 	Lock il(_initLock);
80 
81 	if (_initState == INIT_STATE_CONNECTING) {
82 		return false;
83 	}
84 	_initState = INIT_STATE_CONNECTING;
85 
86 	_cb = cb;
87 	_cbParam = param;
88 
89 	if (_heci.Init(LMS_PROCOL_VERSION)) {
90 		protocolVer = _heci.GetProtocolVersion();
91 		_pHeci = &_heci;
92 	} else if (_heciCompat.Init()) {
93 		protocolVer = _heciCompat.GetProtocolVersion();
94 		if (protocolVer > LMS_PROCOL_VERSION_COMPAT) {
95 			_heciCompat.Deinit();
96 			_initState = INIT_STATE_DISCONNECTED;
97 			return false;
98 		}
99 		_pHeci = &_heciCompat;
100 	} else {
101 		_initState = INIT_STATE_DISCONNECTED;
102 		return false;
103 	}
104 
105 	_initState = INIT_STATE_CONNECTED;
106 
107 	plugin.version(protocolVer);
108 
109 	// launch RX thread
110 	_txBuffer = new unsigned char[_pHeci->GetBufferSize()];
111 	_rxThread = new Thread(_rxThreadFunc, this);
112 	_rxThread->start();
113 
114 	_threadStartedEvent.wait();
115 	return true;
116 }
117 
118 void LMEConnection::Deinit()
119 {
120 	Lock il(_initLock);
121 
122 	_initState = INIT_STATE_DISCONNECTED;
123 
124 	if (_pHeci != NULL) {
125 		_pHeci->Deinit();
126 		_pHeci = NULL;
127 	}
128 
129 	if (_rxThread != NULL) {
130 		delete _rxThread;
131 		_rxThread = NULL;
132 	}
133 
134 	if (_txBuffer != NULL) {
135 		delete[] _txBuffer;
136 		_txBuffer = NULL;
137 	}
138 }
139 
140 bool LMEConnection::Disconnect(APF_DISCONNECT_REASON_CODE reasonCode)
141 {
142 	if (!IsInitialized()) {
143 		PRINT("State: not connected to HECI.\n");
144 		return false;
145 	}
146 
147 	unsigned char buf[sizeof(APF_DISCONNECT_MESSAGE)];
148 
149 	APF_DISCONNECT_MESSAGE *disconnectMessage = (APF_DISCONNECT_MESSAGE *)buf;
150 
151 	memset(disconnectMessage, 0, sizeof(buf));
152 	disconnectMessage->MessageType = APF_DISCONNECT;
153 	disconnectMessage->ReasonCode = htonl(reasonCode);
154 
155 	PRINT("Sending disconnect to LME.\n");
156 	int res = _sendMessage(buf, sizeof(buf));
157 
158 	return (res == sizeof(buf));
159 }
160 
161 bool LMEConnection::ServiceAccept(std::string serviceName)
162 {
163 	if (!IsInitialized()) {
164 		PRINT("State: not connected to HECI.\n");
165 		return false;
166 	}
167 
168 	//APF_SERVICE_ACCEPT_MESSAGE
169 	//memcpy(pCurrent, "127.0.0.1", APF_STR_SIZE_OF("127.0.0.1"));
170 	//pCurrent += APF_STR_SIZE_OF("127.0.0.1");
171 	unsigned char *buf = new unsigned char[sizeof(APF_SERVICE_ACCEPT_MESSAGE) + serviceName.length()];
172 	if (buf == NULL) {
173 		PRINT("Failed to allocate memory for ServiceAccept.\n");
174 		return false;
175 	}
176 
177 	unsigned char *pCurrent = buf;
178 	*pCurrent = APF_SERVICE_ACCEPT;
179 	++pCurrent;
180 	*((UINT32 *)pCurrent) = htonl(serviceName.size());
181 	pCurrent += 4;
182 
183 	memcpy(pCurrent, serviceName.c_str(), serviceName.size());
184 	pCurrent += serviceName.size();
185 
186 	PRINT("Sending service accept to LME: %s\n", serviceName.c_str());
187 	int len = pCurrent - buf;
188 	int res = _sendMessage(buf, len);
189 
190 	delete [] buf;
191 
192 	return (res == len);
193 }
194 
195 bool LMEConnection::UserAuthSuccess()
196 {
197 	if (!IsInitialized()) {
198 		PRINT("State: not connected to HECI.\n");
199 		return false;
200 	}
201 
202 	unsigned char buf = APF_USERAUTH_SUCCESS;
203 
204 	PRINT("Sending user authentication success to LME.\n");
205 	int res = _sendMessage(&buf, sizeof(buf));
206 
207 	return (res == sizeof(buf));
208 }
209 
210 bool LMEConnection::ProtocolVersion(const LMEProtocolVersionMessage versionMessage)
211 {
212 	if (!IsInitialized()) {
213 		PRINT("State: not connected to HECI.\n");
214 		return false;
215 	}
216 
217 	APF_PROTOCOL_VERSION_MESSAGE protVersion;
218 	memset(&protVersion, 0, sizeof(protVersion));
219 
220 	protVersion.MessageType = APF_PROTOCOLVERSION;
221 	protVersion.MajorVersion = htonl(versionMessage.MajorVersion);
222 	protVersion.MinorVersion = htonl(versionMessage.MinorVersion);
223 	protVersion.TriggerReason = htonl(versionMessage.TriggerReason);
224 
225 	PRINT("Sending protocol version to LME: %d.%d\n", versionMessage.MajorVersion, versionMessage.MinorVersion);
226 	int res = _sendMessage((unsigned char *)&protVersion, sizeof(protVersion));
227 
228 	return (res == sizeof(protVersion));
229 }
230 
231 bool LMEConnection::TcpForwardReplySuccess(UINT32 port)
232 {
233 	if (!IsInitialized()) {
234 		PRINT("State: not connected to HECI.\n");
235 		return false;
236 	}
237 
238 	APF_TCP_FORWARD_REPLY_MESSAGE message;
239 
240 	message.MessageType = APF_REQUEST_SUCCESS;
241 	message.PortBound = htonl(port);
242 
243 	PRINT("Sending TCP forward replay success to LME: Port %d.\n", port);
244 	int res = _sendMessage((unsigned char *)&message, sizeof(message));
245 
246 	return (res == sizeof(message));
247 }
248 
249 bool LMEConnection::TcpForwardReplyFailure()
250 {
251 	if (!IsInitialized()) {
252 		PRINT("State: not connected to HECI.\n");
253 		return false;
254 	}
255 
256 	unsigned char buf = APF_REQUEST_FAILURE;
257 
258 	PRINT("Sending TCP forward replay failure to LME.\n");
259 	int res = _sendMessage(&buf, sizeof(buf));
260 
261 	return (res == sizeof(buf));
262 }
263 
264 bool LMEConnection::TcpForwardCancelReplySuccess()
265 {
266 	if (!IsInitialized()) {
267 		PRINT("State: not connected to HECI.\n");
268 		return false;
269 	}
270 
271 	unsigned char buf = APF_REQUEST_SUCCESS;
272 
273 	PRINT("Sending TCP forward cancel replay success to LME.\n");
274 	int res = _sendMessage(&buf, sizeof(buf));
275 
276 	return (res == sizeof(buf));
277 }
278 
279 bool LMEConnection::TcpForwardCancelReplyFailure()
280 {
281 	if (!IsInitialized()) {
282 		PRINT("State: not connected to HECI.\n");
283 		return false;
284 	}
285 
286 	unsigned char buf = APF_REQUEST_FAILURE;
287 
288 	PRINT("Sending TCP forward cancel replay failure to LME.\n");
289 	int res = _sendMessage(&buf, sizeof(buf));
290 
291 	return (res == sizeof(buf));
292 }
293 
294 bool LMEConnection::ChannelOpenForwardedRequest(UINT32 senderChannel,
295 						UINT32 connectedPort,
296 						std::string originatorIP,
297 						UINT32 originatorPort)
298 {
299 	if (!IsInitialized()) {
300 		PRINT("State: not connected to HECI.\n");
301 		return false;
302 	}
303 
304 	unsigned char buf[5 + APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED) + 16 +
305 		APF_STR_SIZE_OF("127.0.0.1") + 8 +  16  + 4];
306 	unsigned char *pCurrent = buf;
307 
308 	if (originatorIP.size() > 16) {
309 		return false;
310 	}
311 
312 	*pCurrent = APF_CHANNEL_OPEN;
313 	++pCurrent;
314 
315 	*((UINT32 *)pCurrent) = htonl(APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED));
316 	pCurrent += sizeof(UINT32);
317 
318 	memcpy(pCurrent, APF_OPEN_CHANNEL_REQUEST_FORWARDED, APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED));
319 	pCurrent += APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED);
320 
321 	*((UINT32 *)pCurrent) = htonl(senderChannel);
322 	pCurrent += sizeof(UINT32);
323 
324 	*((UINT32 *)pCurrent) = htonl(RX_WINDOW_SIZE);
325 	pCurrent += sizeof(UINT32);
326 
327 	*((UINT32 *)pCurrent) = 0xFFFFFFFF;
328 	pCurrent += sizeof(UINT32);
329 
330 	*((UINT32 *)pCurrent) = htonl(APF_STR_SIZE_OF("127.0.0.1"));
331 	pCurrent += sizeof(UINT32);
332 
333 	memcpy(pCurrent, "127.0.0.1", APF_STR_SIZE_OF("127.0.0.1"));
334 	pCurrent += APF_STR_SIZE_OF("127.0.0.1");
335 
336 	*((UINT32 *)pCurrent) = htonl(connectedPort);
337 	pCurrent += sizeof(UINT32);
338 
339 	*((UINT32 *)pCurrent) = htonl((UINT32)originatorIP.size());
340 	pCurrent += sizeof(UINT32);
341 
342 	memcpy(pCurrent, originatorIP.c_str(), originatorIP.size());
343 	pCurrent += originatorIP.size();
344 
345 	*((UINT32 *)pCurrent) = htonl(originatorPort);
346 	pCurrent += sizeof(UINT32);
347 
348 	PRINT("Sending channel open request to LME. Address: %s, requested port: %d.\n",
349 		originatorIP.c_str(), connectedPort);
350 	int res = _sendMessage(buf, (int)(pCurrent - buf));
351 
352 	return (res == pCurrent - buf);
353 }
354 
355 bool LMEConnection::ChannelOpenReplaySuccess(UINT32 recipientChannel,
356 					     UINT32 senderChannel)
357 {
358 	if (!IsInitialized()) {
359 		PRINT("State: not connected to HECI.\n");
360 		return false;
361 	}
362 
363 	APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE message;
364 
365 	message.MessageType = APF_CHANNEL_OPEN_CONFIRMATION;
366 	message.RecipientChannel = htonl(recipientChannel);
367 	message.SenderChannel = htonl(senderChannel);
368 	message.InitialWindowSize = htonl(RX_WINDOW_SIZE);
369 	message.Reserved = 0xFFFFFFFF;
370 
371 	PRINT("Sending channel open replay success to LME. Recipient: %d.\n", recipientChannel);
372 	int res = _sendMessage((unsigned char *)&message, sizeof(message));
373 
374 	return (res == sizeof(message));
375 }
376 
377 bool LMEConnection::ChannelOpenReplayFailure(UINT32 recipientChannel,
378 					     UINT32 reason)
379 {
380 	if (!IsInitialized()) {
381 		PRINT("State: not connected to HECI.\n");
382 		return false;
383 	}
384 
385 	APF_CHANNEL_OPEN_FAILURE_MESSAGE message;
386 
387 	message.MessageType = APF_CHANNEL_OPEN_FAILURE;
388 	message.RecipientChannel = htonl(recipientChannel);
389 	message.ReasonCode = htonl(reason);
390 	message.Reserved = 0x00000000;
391 	message.Reserved2 = 0x00000000;
392 
393 	PRINT("Sending channel open replay failure to LME. Recipient: %d, Reason: %d.\n", recipientChannel, reason);
394 	int res = _sendMessage((unsigned char *)&message, sizeof(message));
395 
396 	return (res == sizeof(message));
397 }
398 
399 bool LMEConnection::ChannelClose(UINT32 recipientChannel)
400 {
401 	if (!IsInitialized()) {
402 		PRINT("State: not connected to HECI.\n");
403 		return false;
404 	}
405 
406 	APF_CHANNEL_CLOSE_MESSAGE message;
407 
408 	message.MessageType = APF_CHANNEL_CLOSE;
409 	message.RecipientChannel = htonl(recipientChannel);
410 
411 	PRINT("Sending channel close to LME. Recipient: %d.\n", recipientChannel);
412 	int res = _sendMessage((unsigned char *)&message, sizeof(message));
413 
414 	return (res == sizeof(message));
415 }
416 
417 int LMEConnection::ChannelData(UINT32 recipientChannel,
418 			       UINT32 len, unsigned char *buffer)
419 {
420 	if (!IsInitialized()) {
421 		PRINT("State: not connected to HECI.\n");
422 		return false;
423 	}
424 
425 	APF_CHANNEL_DATA_MESSAGE *message;
426 
427 	if (len > _heci.GetBufferSize() - sizeof(APF_CHANNEL_DATA_MESSAGE)) {
428 		return -1;
429 	}
430 
431 	message = (APF_CHANNEL_DATA_MESSAGE *)_txBuffer;
432 	message->MessageType = APF_CHANNEL_DATA;
433 	message->RecipientChannel = htonl(recipientChannel);
434 	message->DataLength = htonl(len);
435 	memcpy(message->Data, buffer, len);
436 
437 	PRINT("Sending %d bytes to recipient channel %d.\n", len, recipientChannel);
438 	return _sendMessage((unsigned char *)message, sizeof(APF_CHANNEL_DATA_MESSAGE) + len);
439 }
440 
441 bool LMEConnection::ChannelWindowAdjust(UINT32 recipientChannel, UINT32 len)
442 {
443 	if (!IsInitialized()) {
444 		PRINT("State: not connected to HECI.\n");
445 		return false;
446 	}
447 
448 	APF_WINDOW_ADJUST_MESSAGE message;
449 
450 	message.MessageType = APF_CHANNEL_WINDOW_ADJUST;
451 	message.RecipientChannel = htonl(recipientChannel);
452 	message.BytesToAdd = htonl(len);
453 
454 	PRINT("Sending Window Adjust with %d bytes to recipient channel %d.\n", len, recipientChannel);
455 	int res = _sendMessage((unsigned char *)&message, sizeof(message));
456 
457 	return (res == sizeof(message));
458 }
459 
460 int LMEConnection::_receiveMessage(unsigned char *buffer, int len)
461 {
462 	int result;
463 
464 	if (!IsInitialized()) {
465 		return -1;
466 	}
467 
468 	result = _pHeci->ReceiveMessage(buffer, len, WAIT_INFINITE);
469 
470 	if (result < 0 && errno == ENOENT) {
471 		Lock il(_initLock);
472 		_initState = INIT_STATE_DISCONNECTED;
473 	}
474 
475 	return result;
476 }
477 
478 int LMEConnection::_sendMessage(unsigned char *buffer, int len)
479 {
480 	int result;
481 
482 	if (!IsInitialized()) {
483 		return -1;
484 	}
485 
486 	_sendMessageLock.acquire();
487 	result = _pHeci->SendMessage(buffer, len, HECI_IO_TIMEOUT);
488 	_sendMessageLock.release();
489 
490 	if (result < 0 && errno == ENOENT) {
491 		Lock il(_initLock);
492 		_initState = INIT_STATE_DISCONNECTED;
493 	}
494 
495 	return result;
496 }
497 
498 void LMEConnection::_rxThreadFunc(void *param)
499 {
500 	LMEConnection *connection = (LMEConnection *)param;
501 
502 	try {
503 		if (LMS_PROCOL_VERSION == connection->protocolVer) {
504 			connection->_doRX();
505 		} else if (LMS_PROCOL_VERSION_COMPAT == connection->protocolVer) {
506 			connection->_doRXCompat();
507 		}
508 	}
509 	catch (...) {
510 		PRINT("LMEConnection do RX exception\n");
511 	}
512 	pthread_exit(NULL);
513 }
514 
515 bool LMEConnection::_checkMinMsgSize(unsigned char *buf, unsigned int bytesRead)
516 {
517 	switch (buf[0]) {
518 	case APF_DISCONNECT:
519 		if (bytesRead < sizeof(APF_DISCONNECT_MESSAGE)) {
520 			return false;
521 		}
522 		break;
523 	case APF_SERVICE_REQUEST:
524 		if (bytesRead < sizeof(APF_SERVICE_REQUEST)) {
525 			return false;
526 		}
527 		if (bytesRead < (sizeof(APF_SERVICE_REQUEST) +
528 			ntohl(((APF_SERVICE_REQUEST_MESSAGE *)buf)->ServiceNameLength))) {
529 			return false;
530 		}
531 		break;
532 	case APF_USERAUTH_REQUEST:
533 		if (bytesRead < (3 * sizeof(UINT32))) {
534 			return false;
535 		}
536 		break;
537 	case APF_GLOBAL_REQUEST:
538 		if (bytesRead < (sizeof(APF_GENERIC_HEADER) + sizeof(UINT8))) {
539 			return false;
540 		}
541 		if (bytesRead < (sizeof(APF_GENERIC_HEADER) + sizeof(UINT8) +
542 			ntohl(((APF_GENERIC_HEADER *)buf)->StringLength))) {
543 			return false;
544 		}
545 		break;
546 	case APF_CHANNEL_OPEN:
547 		if (bytesRead < sizeof(APF_GENERIC_HEADER)) {
548 			return false;
549 		}
550 		if (bytesRead < (sizeof(APF_GENERIC_HEADER) +
551 			ntohl(((APF_GENERIC_HEADER *)buf)->StringLength))) {
552 			return false;
553 		}
554 		break;
555 	case APF_CHANNEL_OPEN_CONFIRMATION:
556 		if (bytesRead < sizeof(APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE)) {
557 			return false;
558 		}
559 		break;
560 	case APF_CHANNEL_OPEN_FAILURE:
561 		if (bytesRead < sizeof(APF_CHANNEL_OPEN_FAILURE_MESSAGE)) {
562 			return false;
563 		}
564 		break;
565 	case APF_CHANNEL_CLOSE:
566 		if (bytesRead < sizeof(APF_CHANNEL_CLOSE_MESSAGE)) {
567 			return false;
568 		}
569 		break;
570 	case APF_CHANNEL_DATA:
571 		if (bytesRead < sizeof(APF_CHANNEL_DATA_MESSAGE)) {
572 			return false;
573 		}
574 		if (bytesRead < (sizeof(APF_CHANNEL_DATA_MESSAGE) +
575 			ntohl(((APF_CHANNEL_DATA_MESSAGE *)buf)->DataLength))) {
576 			return false;
577 		}
578 		break;
579 	case APF_CHANNEL_WINDOW_ADJUST:
580 		if (bytesRead < sizeof(APF_WINDOW_ADJUST_MESSAGE)) {
581 			return false;
582 		}
583 		break;
584 	case APF_PROTOCOLVERSION:
585 		if (bytesRead < sizeof(APF_PROTOCOL_VERSION_MESSAGE)) {
586 			return false;
587 		}
588 		break;
589 	default:
590 		return false;
591 	}
592 	return true;
593 }
594 
595 void LMEConnection::_doRX()
596 {
597 	unsigned int bytesRead;
598 	int status = 1;
599 
600 	_threadStartedEvent.set();
601 
602 	unsigned char *rxBuffer = new unsigned char[_heci.GetBufferSize()];
603 
604 	while (true) {
605 		bytesRead = (unsigned int)_receiveMessage(rxBuffer, _heci.GetBufferSize());
606 
607 		if ((int)bytesRead < 0) {
608 			PRINT("Error receiving data from HECI\n");
609 			Deinit();
610 			break;
611 		}
612 
613 		if (bytesRead == 0) {
614 			// ERROR
615 			continue;
616 		}
617 
618 		PRINT("Received from LME %d bytes (msg type %02d)\n", bytesRead, rxBuffer[0]);
619 
620 		if (!_checkMinMsgSize(rxBuffer, bytesRead)) {
621 			PRINT("Error receiving data from HECI\n");
622 			Deinit();
623 			break;
624 		}
625 
626 		if (plugin.preprocess(rxBuffer, bytesRead) == LMS_DROPPED) {
627 			continue;
628 		}
629 
630 		switch (rxBuffer[0]) {
631 		case APF_DISCONNECT:
632 			{
633 				LMEDisconnectMessage disconnectMessage(
634 				    (APF_DISCONNECT_REASON_CODE)ntohl(
635 					((APF_DISCONNECT_MESSAGE *)rxBuffer)->ReasonCode));
636 
637 				_cb(_cbParam, &disconnectMessage, sizeof(disconnectMessage), &status);
638 			}
639 			break;
640 
641 		case APF_SERVICE_REQUEST:
642 			{
643 				APF_SERVICE_REQUEST_MESSAGE *pMessage =
644 					(APF_SERVICE_REQUEST_MESSAGE *)rxBuffer;
645 				LMEServiceRequestMessage serviceRequestMessage;
646 
647 				serviceRequestMessage.ServiceName.append(
648 					(char *)(pMessage->ServiceName),
649 					ntohl(pMessage->ServiceNameLength));
650 
651 				_cb(_cbParam, &serviceRequestMessage, sizeof(serviceRequestMessage), &status);
652 			}
653 			break;
654 
655 		case APF_USERAUTH_REQUEST:
656 			_apfUserAuthRequest(rxBuffer, bytesRead, &status);
657 			break;
658 
659 		case APF_GLOBAL_REQUEST:
660 			_apfGlobalRequest(rxBuffer, bytesRead, &status);
661 			break;
662 
663 		case APF_CHANNEL_OPEN:
664 			_apfChannelOpen(rxBuffer, bytesRead, &status);
665 			break;
666 
667 		case APF_CHANNEL_OPEN_CONFIRMATION:
668 			{
669 				APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE *pMessage =
670 				    (APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE *)rxBuffer;
671 				LMEChannelOpenReplaySuccessMessage channelOpenReply;
672 
673 				channelOpenReply.RecipientChannel = ntohl(pMessage->RecipientChannel);
674 				channelOpenReply.SenderChannel = ntohl(pMessage->SenderChannel);
675 				channelOpenReply.InitialWindow = ntohl(pMessage->InitialWindowSize);
676 				_cb(_cbParam, &channelOpenReply, sizeof(channelOpenReply), &status);
677 			}
678 			break;
679 
680 		case APF_CHANNEL_OPEN_FAILURE:
681 			{
682 				APF_CHANNEL_OPEN_FAILURE_MESSAGE *pMessage =
683 				    (APF_CHANNEL_OPEN_FAILURE_MESSAGE *)rxBuffer;
684 				LMEChannelOpenReplayFailureMessage channelOpenReply;
685 
686 				channelOpenReply.RecipientChannel = ntohl(pMessage->RecipientChannel);
687 				channelOpenReply.ReasonCode =
688 					(OPEN_FAILURE_REASON)(ntohl(pMessage->ReasonCode));
689 				_cb(_cbParam, &channelOpenReply, sizeof(channelOpenReply), &status);
690 			}
691 			break;
692 
693 		case APF_CHANNEL_CLOSE:
694 			{
695 				APF_CHANNEL_CLOSE_MESSAGE *pMessage =
696 				    (APF_CHANNEL_CLOSE_MESSAGE *)rxBuffer;
697 				LMEChannelCloseMessage channelClose;
698 
699 				channelClose.RecipientChannel = ntohl(pMessage->RecipientChannel);
700 				_cb(_cbParam, &channelClose, sizeof(channelClose), &status);
701 			}
702 			break;
703 
704 		case APF_CHANNEL_DATA:
705 			{
706 				APF_CHANNEL_DATA_MESSAGE *pMessage =
707 				    (APF_CHANNEL_DATA_MESSAGE *)rxBuffer;
708 				LMEChannelDataMessage channelData(ntohl(pMessage->RecipientChannel),
709 								  ntohl(pMessage->DataLength),
710 								  pMessage->Data);
711 				_cb(_cbParam, &channelData, sizeof(channelData), &status);
712 			}
713 			break;
714 
715 		case APF_CHANNEL_WINDOW_ADJUST:
716 			{
717 				APF_WINDOW_ADJUST_MESSAGE *pMessage =
718 				    (APF_WINDOW_ADJUST_MESSAGE *)rxBuffer;
719 				LMEChannelWindowAdjustMessage channelWindowAdjust;
720 
721 				channelWindowAdjust.RecipientChannel = ntohl(pMessage->RecipientChannel);
722 				channelWindowAdjust.BytesToAdd = ntohl(pMessage->BytesToAdd);
723 				_cb(_cbParam, &channelWindowAdjust, sizeof(channelWindowAdjust), &status);
724 			}
725 			break;
726 
727 		case APF_PROTOCOLVERSION:
728 			{
729 				APF_PROTOCOL_VERSION_MESSAGE *pMessage =
730 				    (APF_PROTOCOL_VERSION_MESSAGE *)rxBuffer;
731 				LMEProtocolVersionMessage protVersion;
732 
733 				protVersion.MajorVersion = ntohl(pMessage->MajorVersion);
734 				protVersion.MinorVersion = ntohl(pMessage->MinorVersion);
735 				protVersion.TriggerReason =
736 					(APF_TRIGGER_REASON)ntohl(pMessage->TriggerReason);
737 				_cb(_cbParam, &protVersion, sizeof(protVersion), &status);
738 			}
739 			break;
740 
741 		default:
742 			// Uknown request. Ignore
743 			break;
744 		}
745 
746 		if (IsInitialized()) {
747 			plugin.postprocess(rxBuffer, bytesRead, status);
748 		}
749 	}
750 
751 	if (rxBuffer != NULL) {
752 		delete[] rxBuffer;
753 	}
754 }
755 
756 void LMEConnection::_apfChannelOpen(unsigned char *rxBuffer, unsigned int bytesRead, int *status)
757 {
758 	APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
759 
760 	if (_strnicmp((char *)pHeader->String,
761 		APF_OPEN_CHANNEL_REQUEST_DIRECT,
762 		APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT)) == 0) {
763 
764 		UINT32 senderChannel = 0;
765 
766 		_apfChannelOpenDirect(rxBuffer, bytesRead, &senderChannel, status);
767 		if (IsInitialized() && (*status == 1)) {
768 			if (plugin.retry(rxBuffer, bytesRead) != LMS_DROPPED) {
769 				_apfChannelOpenDirect(rxBuffer, bytesRead, NULL, status);
770 			}
771 		}
772 		if (IsInitialized() && (*status == 1)) {
773 			ChannelOpenReplayFailure(senderChannel,
774 			    OPEN_FAILURE_REASON_CONNECT_FAILED);
775 		}
776 	}
777 }
778 
779 void LMEConnection::_apfChannelOpenDirect(unsigned char *rxBuffer, unsigned int bytesRead, UINT32 *senderChannel, int *status)
780 {
781 	unsigned char *pCurrent;
782 	APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
783 
784 	if (bytesRead < sizeof(APF_GENERIC_HEADER) +
785 	    ntohl(pHeader->StringLength) +
786 	    7 + (5 * sizeof(UINT32))) {
787 		PRINT("Error receiving data from HECI\n");
788 		Deinit();
789 		return;
790 	}
791 
792 	pCurrent = rxBuffer + sizeof(APF_GENERIC_HEADER) +
793 		APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT);
794 
795 	LMEChannelOpenRequestMessage channelOpenRequest;
796 	channelOpenRequest.ChannelType = LMEChannelOpenRequestMessage::DIRECT;
797 
798 	channelOpenRequest.SenderChannel = ntohl(*((UINT32 *)pCurrent));
799 	if (senderChannel) {
800 		*senderChannel = channelOpenRequest.SenderChannel;
801 	}
802 	pCurrent += sizeof(UINT32);
803 	channelOpenRequest.InitialWindow = ntohl(*((UINT32 *)pCurrent));
804 	pCurrent += 2 * sizeof(UINT32);
805 
806 	UINT32 len = ntohl(*((UINT32 *)pCurrent));
807 	pCurrent += sizeof(UINT32);
808 	channelOpenRequest.Address.append((char *)pCurrent, len);
809 	pCurrent += len;
810 	channelOpenRequest.Port = ntohl(*((UINT32 *)pCurrent));
811 	pCurrent += sizeof(UINT32);
812 
813 	_cb(_cbParam, &channelOpenRequest, sizeof(channelOpenRequest), status);
814 }
815 
816 void LMEConnection::_apfGlobalRequest(unsigned char *rxBuffer, unsigned int bytesRead, int *status)
817 {
818 	unsigned char *pCurrent;
819 	APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
820 
821 	if (_strnicmp((char *)pHeader->String,
822 	    APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST,
823 	    APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST)) == 0) {
824 		LMETcpForwardRequestMessage tcpForwardRequest;
825 		unsigned int hsize = sizeof(APF_GENERIC_HEADER) +
826 		    APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST) +
827 		    sizeof(UINT8);
828 		pCurrent = rxBuffer + hsize;
829 		bytesRead -= hsize;
830 
831 		if (bytesRead < sizeof(UINT32)) {
832 			PRINT("Error receiving data from HECI\n");
833 			Deinit();
834 			return;
835 		}
836 
837 		UINT32 len = ntohl(*((UINT32 *)pCurrent));
838 		pCurrent += sizeof(UINT32);
839 
840 		if (bytesRead < (sizeof(UINT32) + len + sizeof(UINT32))) {
841 			PRINT("Error receiving data from HECI\n");
842 			Deinit();
843 			return;
844 		}
845 
846 		tcpForwardRequest.Address.append((char *)pCurrent, len);
847 		pCurrent += len;
848 		tcpForwardRequest.Port = ntohl(*((UINT32 *)pCurrent));
849 
850 		_cb(_cbParam, &tcpForwardRequest, sizeof(tcpForwardRequest), status);
851 	}
852 	else if (_strnicmp((char *)pHeader->String,
853 	    APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST,
854 	    APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST)) == 0) {
855 		LMETcpForwardCancelRequestMessage tcpForwardCancelRequest;
856 		unsigned int hsize = sizeof(APF_GENERIC_HEADER) +
857 		    APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST) +
858 		    sizeof(UINT8);
859 		pCurrent = rxBuffer + hsize;
860 		bytesRead -= hsize;
861 
862 		if (bytesRead < sizeof(UINT32)) {
863 			PRINT("Error receiving data from HECI\n");
864 			Deinit();
865 			return;
866 		}
867 
868 		UINT32 len = ntohl(*((UINT32 *)pCurrent));
869 		pCurrent += sizeof(UINT32);
870 
871 		if (bytesRead < (sizeof(UINT32) + len + sizeof(UINT32))) {
872 			PRINT("Error receiving data from HECI\n");
873 			Deinit();
874 			return;
875 		}
876 
877 		tcpForwardCancelRequest.Address.append((char *)pCurrent, len);
878 		pCurrent += len;
879 		tcpForwardCancelRequest.Port = ntohl(*((UINT32 *)pCurrent));
880 
881 		_cb(_cbParam, &tcpForwardCancelRequest, sizeof(tcpForwardCancelRequest), status);
882 	}
883 	else if (_strnicmp((char *)pHeader->String,
884 	    APF_GLOBAL_REQUEST_STR_UDP_SEND_TO,
885 	    APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_UDP_SEND_TO)) == 0) {
886 		unsigned int hsize = sizeof(APF_GENERIC_HEADER) +
887 		    APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_UDP_SEND_TO) +
888 		    sizeof(UINT8);
889 		pCurrent = rxBuffer + hsize;
890 		bytesRead -= hsize;
891 
892 		if (bytesRead < sizeof(UINT32)) {
893 			PRINT("Error receiving data from HECI\n");
894 			Deinit();
895 			return;
896 		}
897 
898 		UINT32 len = ntohl(*((UINT32 *)pCurrent));
899 		pCurrent += sizeof(UINT32);
900 
901 		if (bytesRead < (sizeof(UINT32) + len + sizeof(UINT32))) {
902 			PRINT("Error receiving data from HECI\n");
903 			Deinit();
904 			return;
905 		}
906 		bytesRead -= (sizeof(UINT32) + len + sizeof(UINT32));
907 
908 		std::string address;
909 		address.append((char *)pCurrent, len);
910 		pCurrent += len;
911 		UINT32 port = ntohl(*((UINT32 *)pCurrent));
912 		pCurrent += sizeof(UINT32);
913 
914 		if (bytesRead < sizeof(UINT32)) {
915 			PRINT("Error receiving data from HECI\n");
916 			Deinit();
917 			return;
918 		}
919 
920 		// Skip Originator IP and Port
921 		len = ntohl(*((UINT32 *)pCurrent));
922 		pCurrent += sizeof(UINT32);
923 
924 		if (bytesRead < (sizeof(UINT32) + len + sizeof(UINT32))) {
925 			PRINT("Error receiving data from HECI\n");
926 			Deinit();
927 			return;
928 		}
929 		bytesRead -= (sizeof(UINT32) + len + sizeof(UINT32));
930 
931 		pCurrent += len;
932 		pCurrent += sizeof(UINT32);
933 
934 		if (bytesRead < sizeof(UINT32)) {
935 			PRINT("Error receiving data from HECI\n");
936 			Deinit();
937 			return;
938 		}
939 
940 		// Retrieve Data
941 		len = ntohl(*((UINT32 *)pCurrent));
942 		pCurrent += sizeof(UINT32);
943 
944 		if (bytesRead < (sizeof(UINT32) + len)) {
945 			PRINT("Error receiving data from HECI\n");
946 			Deinit();
947 			return;
948 		}
949 
950 		LMEUdpSendToMessage udpSendTo(address, port, len, pCurrent);
951 
952 		_cb(_cbParam, &udpSendTo, sizeof(udpSendTo), status);
953 	}
954 }
955 
956 void LMEConnection::_apfUserAuthRequest(unsigned char *rxBuffer, unsigned int bytesRead, int *status)
957 {
958 	unsigned char *pCurrent = rxBuffer;
959 
960 	++pCurrent;
961 
962 	LMEUserAuthRequestMessage userAuthRequest;
963 
964 	UINT32 len = ntohl(*((UINT32 *)pCurrent));
965 	pCurrent += sizeof(UINT32);
966 
967 	if ((bytesRead - (pCurrent - rxBuffer)) < len) {
968 		PRINT("Error receiving data from HECI\n");
969 		Deinit();
970 		return;
971 	}
972 
973 	userAuthRequest.Username.append((char *)pCurrent, len);
974 	pCurrent += len;
975 
976 	if ((unsigned int)(bytesRead - (pCurrent - rxBuffer)) < sizeof(UINT32)) {
977 		PRINT("Error receiving data from HECI\n");
978 		Deinit();
979 		return;
980 	}
981 
982 	len = ntohl(*((UINT32 *)pCurrent));
983 	pCurrent += sizeof(UINT32);
984 
985 	if ((bytesRead - (pCurrent - rxBuffer)) < len) {
986 		PRINT("Error receiving data from HECI\n");
987 		Deinit();
988 		return;
989 	}
990 
991 	userAuthRequest.ServiceName.append((char *)pCurrent, len);
992 	pCurrent += len;
993 
994 	if ((unsigned int)(bytesRead - (pCurrent - rxBuffer)) < sizeof(UINT32)) {
995 		PRINT("Error receiving data from HECI\n");
996 		Deinit();
997 		return;
998 	}
999 
1000 	len = ntohl(*((UINT32 *)pCurrent));
1001 	pCurrent += sizeof(UINT32);
1002 
1003 	if ((bytesRead - (pCurrent - rxBuffer)) < len) {
1004 		PRINT("Error receiving data from HECI\n");
1005 		Deinit();
1006 		return;
1007 	}
1008 
1009 	userAuthRequest.MethodName.append((char *)pCurrent, len);
1010 	pCurrent += len;
1011 
1012 	if (_strnicmp(userAuthRequest.MethodName.c_str(), APF_AUTH_PASSWORD,
1013 			userAuthRequest.MethodName.size()) == 0) {
1014 
1015 		if ((unsigned int)(bytesRead - (pCurrent - rxBuffer)) < sizeof(UINT32) + 1) {
1016 			PRINT("Error receiving data from HECI\n");
1017 			Deinit();
1018 			return;
1019 		}
1020 
1021 		++pCurrent;
1022 
1023 		len = ntohl(*((UINT32 *)pCurrent));
1024 		pCurrent += sizeof(UINT32);
1025 
1026 		if ((bytesRead - (pCurrent - rxBuffer)) < len) {
1027 			PRINT("Error receiving data from HECI\n");
1028 			Deinit();
1029 			return;
1030 		}
1031 
1032 		AuthPasswordData authData;
1033 		authData.Password.append((char *)pCurrent, len);
1034 		pCurrent += len;
1035 
1036 		userAuthRequest.MethodData = &authData;
1037 	}
1038 
1039 	_cb(_cbParam, &userAuthRequest, sizeof(userAuthRequest), status);
1040 }
1041 
1042 unsigned int LMEConnection::GetHeciBufferSize() const
1043 {
1044 	if (_pHeci == NULL) {
1045 		return 0;
1046 	}
1047 	return _pHeci->GetBufferSize();
1048 }
1049 
1050