24#include <freerdp/config.h>
27#include <winpr/assert.h>
28#include <freerdp/log.h>
36#include "connection.h"
38#define MCS_TAG FREERDP_TAG("core")
169static const BYTE callingDomainSelector[1] = { 0x01 };
170static const BYTE calledDomainSelector[1] = { 0x01 };
194const char* mcs_domain_pdu_string(DomainMCSPDU pdu)
198 case DomainMCSPDU_PlumbDomainIndication:
199 return "DomainMCSPDU_PlumbDomainIndication";
200 case DomainMCSPDU_ErectDomainRequest:
201 return "DomainMCSPDU_ErectDomainRequest";
202 case DomainMCSPDU_MergeChannelsRequest:
203 return "DomainMCSPDU_MergeChannelsRequest";
204 case DomainMCSPDU_MergeChannelsConfirm:
205 return "DomainMCSPDU_MergeChannelsConfirm";
206 case DomainMCSPDU_PurgeChannelsIndication:
207 return "DomainMCSPDU_PurgeChannelsIndication";
208 case DomainMCSPDU_MergeTokensRequest:
209 return "DomainMCSPDU_MergeTokensRequest";
210 case DomainMCSPDU_MergeTokensConfirm:
211 return "DomainMCSPDU_MergeTokensConfirm";
212 case DomainMCSPDU_PurgeTokensIndication:
213 return "DomainMCSPDU_PurgeTokensIndication";
214 case DomainMCSPDU_DisconnectProviderUltimatum:
215 return "DomainMCSPDU_DisconnectProviderUltimatum";
216 case DomainMCSPDU_RejectMCSPDUUltimatum:
217 return "DomainMCSPDU_RejectMCSPDUUltimatum";
218 case DomainMCSPDU_AttachUserRequest:
219 return "DomainMCSPDU_AttachUserRequest";
220 case DomainMCSPDU_AttachUserConfirm:
221 return "DomainMCSPDU_AttachUserConfirm";
222 case DomainMCSPDU_DetachUserRequest:
223 return "DomainMCSPDU_DetachUserRequest";
224 case DomainMCSPDU_DetachUserIndication:
225 return "DomainMCSPDU_DetachUserIndication";
226 case DomainMCSPDU_ChannelJoinRequest:
227 return "DomainMCSPDU_ChannelJoinRequest";
228 case DomainMCSPDU_ChannelJoinConfirm:
229 return "DomainMCSPDU_ChannelJoinConfirm";
230 case DomainMCSPDU_ChannelLeaveRequest:
231 return "DomainMCSPDU_ChannelLeaveRequest";
232 case DomainMCSPDU_ChannelConveneRequest:
233 return "DomainMCSPDU_ChannelConveneRequest";
234 case DomainMCSPDU_ChannelConveneConfirm:
235 return "DomainMCSPDU_ChannelConveneConfirm";
236 case DomainMCSPDU_ChannelDisbandRequest:
237 return "DomainMCSPDU_ChannelDisbandRequest";
238 case DomainMCSPDU_ChannelDisbandIndication:
239 return "DomainMCSPDU_ChannelDisbandIndication";
240 case DomainMCSPDU_ChannelAdmitRequest:
241 return "DomainMCSPDU_ChannelAdmitRequest";
242 case DomainMCSPDU_ChannelAdmitIndication:
243 return "DomainMCSPDU_ChannelAdmitIndication";
244 case DomainMCSPDU_ChannelExpelRequest:
245 return "DomainMCSPDU_ChannelExpelRequest";
246 case DomainMCSPDU_ChannelExpelIndication:
247 return "DomainMCSPDU_ChannelExpelIndication";
248 case DomainMCSPDU_SendDataRequest:
249 return "DomainMCSPDU_SendDataRequest";
250 case DomainMCSPDU_SendDataIndication:
251 return "DomainMCSPDU_SendDataIndication";
252 case DomainMCSPDU_UniformSendDataRequest:
253 return "DomainMCSPDU_UniformSendDataRequest";
254 case DomainMCSPDU_UniformSendDataIndication:
255 return "DomainMCSPDU_UniformSendDataIndication";
256 case DomainMCSPDU_TokenGrabRequest:
257 return "DomainMCSPDU_TokenGrabRequest";
258 case DomainMCSPDU_TokenGrabConfirm:
259 return "DomainMCSPDU_TokenGrabConfirm";
260 case DomainMCSPDU_TokenInhibitRequest:
261 return "DomainMCSPDU_TokenInhibitRequest";
262 case DomainMCSPDU_TokenInhibitConfirm:
263 return "DomainMCSPDU_TokenInhibitConfirm";
264 case DomainMCSPDU_TokenGiveRequest:
265 return "DomainMCSPDU_TokenGiveRequest";
266 case DomainMCSPDU_TokenGiveIndication:
267 return "DomainMCSPDU_TokenGiveIndication";
268 case DomainMCSPDU_TokenGiveResponse:
269 return "DomainMCSPDU_TokenGiveResponse";
270 case DomainMCSPDU_TokenGiveConfirm:
271 return "DomainMCSPDU_TokenGiveConfirm";
272 case DomainMCSPDU_TokenPleaseRequest:
273 return "DomainMCSPDU_TokenPleaseRequest";
274 case DomainMCSPDU_TokenPleaseConfirm:
275 return "DomainMCSPDU_TokenPleaseConfirm";
276 case DomainMCSPDU_TokenReleaseRequest:
277 return "DomainMCSPDU_TokenReleaseRequest";
278 case DomainMCSPDU_TokenReleaseConfirm:
279 return "DomainMCSPDU_TokenReleaseConfirm";
280 case DomainMCSPDU_TokenTestRequest:
281 return "DomainMCSPDU_TokenTestRequest";
282 case DomainMCSPDU_TokenTestConfirm:
283 return "DomainMCSPDU_TokenTestConfirm";
284 case DomainMCSPDU_enum_length:
285 return "DomainMCSPDU_enum_length";
287 return "DomainMCSPDU_UNKNOWN";
291static BOOL mcs_merge_domain_parameters(wLog* log,
DomainParameters* targetParameters,
296static BOOL mcs_write_connect_initial(
wStream* s, rdpMcs* mcs,
wStream* userData);
297static BOOL mcs_write_connect_response(
wStream* s, rdpMcs* mcs,
wStream* userData);
298static BOOL mcs_read_domain_mcspdu_header(wLog* log,
wStream* s, DomainMCSPDU domainMCSPDU,
299 UINT16* length, DomainMCSPDU* actual);
301static int mcs_initialize_client_channels(rdpMcs* mcs,
const rdpSettings* settings)
303 if (!mcs || !settings)
308 if (mcs->channelCount > mcs->channelMaxCount)
309 mcs->channelCount = mcs->channelMaxCount;
311 ZeroMemory(mcs->channels,
sizeof(rdpMcsChannel) * mcs->channelMaxCount);
313 for (UINT32 index = 0; index < mcs->channelCount; index++)
316 freerdp_settings_get_pointer_array(settings, FreeRDP_ChannelDefArray, index);
317 rdpMcsChannel* cur = &mcs->channels[index];
318 WINPR_ASSERT(defchannel);
319 CopyMemory(cur->Name, defchannel->name, CHANNEL_NAME_LEN);
320 cur->options = defchannel->options;
335BOOL mcs_read_domain_mcspdu_header(wLog* log,
wStream* s, DomainMCSPDU domainMCSPDU, UINT16* length,
336 DomainMCSPDU* actual)
342 *actual = DomainMCSPDU_invalid;
345 WINPR_ASSERT(domainMCSPDU);
346 WINPR_ASSERT(length);
348 if (!tpkt_read_header(s, length))
351 if (!tpdu_read_data(s, &li, *length))
354 if (!per_read_choice(s, &choice))
357 const BYTE val = choice >> 2;
358 const DomainMCSPDU MCSPDU =
359 (val > DomainMCSPDU_enum_length) ? DomainMCSPDU_invalid : (DomainMCSPDU)(val);
363 if (domainMCSPDU != MCSPDU)
365 WLog_Print(log, WLOG_ERROR,
"Expected MCS %s, got %s", mcs_domain_pdu_string(domainMCSPDU),
366 mcs_domain_pdu_string(MCSPDU));
380BOOL mcs_write_domain_mcspdu_header(
wStream* s, DomainMCSPDU domainMCSPDU, UINT16 length,
384 WINPR_ASSERT((options & ~0x03) == 0);
385 WINPR_ASSERT((domainMCSPDU & ~0x3F) == 0);
387 if (!tpkt_write_header(s, length))
389 if (!tpdu_write_data(s))
391 return per_write_choice(s, (BYTE)((domainMCSPDU << 2) | options));
403static BOOL mcs_init_domain_parameters(
DomainParameters* domainParameters, UINT32 maxChannelIds,
404 UINT32 maxUserIds, UINT32 maxTokenIds, UINT32 maxMCSPDUsize)
406 if (!domainParameters)
409 domainParameters->maxChannelIds = maxChannelIds;
410 domainParameters->maxUserIds = maxUserIds;
411 domainParameters->maxTokenIds = maxTokenIds;
412 domainParameters->maxMCSPDUsize = maxMCSPDUsize;
413 domainParameters->numPriorities = 1;
414 domainParameters->minThroughput = 0;
415 domainParameters->maxHeight = 1;
416 domainParameters->protocolVersion = 2;
430 if (!s || !domainParameters)
433 return ber_read_sequence_tag(s, &length) &&
434 ber_read_integer(s, &(domainParameters->maxChannelIds)) &&
435 ber_read_integer(s, &(domainParameters->maxUserIds)) &&
436 ber_read_integer(s, &(domainParameters->maxTokenIds)) &&
437 ber_read_integer(s, &(domainParameters->numPriorities)) &&
438 ber_read_integer(s, &(domainParameters->minThroughput)) &&
439 ber_read_integer(s, &(domainParameters->maxHeight)) &&
440 ber_read_integer(s, &(domainParameters->maxMCSPDUsize)) &&
441 ber_read_integer(s, &(domainParameters->protocolVersion));
455 if (!s || !domainParameters)
458 wStream* tmps = Stream_New(
nullptr, Stream_Capacity(s));
462 WLog_Print(log, WLOG_ERROR,
"Stream_New failed!");
466 if (!ber_write_integer(tmps, domainParameters->maxChannelIds))
468 if (!ber_write_integer(tmps, domainParameters->maxUserIds))
470 if (!ber_write_integer(tmps, domainParameters->maxTokenIds))
472 if (!ber_write_integer(tmps, domainParameters->numPriorities))
474 if (!ber_write_integer(tmps, domainParameters->minThroughput))
476 if (!ber_write_integer(tmps, domainParameters->maxHeight))
478 if (!ber_write_integer(tmps, domainParameters->maxMCSPDUsize))
480 if (!ber_write_integer(tmps, domainParameters->protocolVersion))
482 length = Stream_GetPosition(tmps);
483 if (!ber_write_sequence_tag(s, length))
485 Stream_Write(s, Stream_Buffer(tmps), length);
489 Stream_Free(tmps, TRUE);
501 WLog_INFO(TAG,
"DomainParameters {");
503 if (domainParameters)
505 WLog_INFO(TAG,
"\tmaxChannelIds:%" PRIu32
"", domainParameters->maxChannelIds);
506 WLog_INFO(TAG,
"\tmaxUserIds:%" PRIu32
"", domainParameters->maxUserIds);
507 WLog_INFO(TAG,
"\tmaxTokenIds:%" PRIu32
"", domainParameters->maxTokenIds);
508 WLog_INFO(TAG,
"\tnumPriorities:%" PRIu32
"", domainParameters->numPriorities);
509 WLog_INFO(TAG,
"\tminThroughput:%" PRIu32
"", domainParameters->minThroughput);
510 WLog_INFO(TAG,
"\tmaxHeight:%" PRIu32
"", domainParameters->maxHeight);
511 WLog_INFO(TAG,
"\tmaxMCSPDUsize:%" PRIu32
"", domainParameters->maxMCSPDUsize);
512 WLog_INFO(TAG,
"\tprotocolVersion:%" PRIu32
"", domainParameters->protocolVersion);
515 WLog_INFO(TAG,
"\tdomainParameters=%p", domainParameters);
531BOOL mcs_merge_domain_parameters(wLog* log,
DomainParameters* targetParameters,
537 if (!targetParameters || !minimumParameters || !maximumParameters || !pOutParameters)
540 if (targetParameters->maxChannelIds >= 4)
542 pOutParameters->maxChannelIds = targetParameters->maxChannelIds;
544 else if (maximumParameters->maxChannelIds >= 4)
546 pOutParameters->maxChannelIds = 4;
550 WLog_Print(log, WLOG_ERROR,
"invalid maxChannelIds [%" PRIu32
", %" PRIu32
"]",
551 targetParameters->maxChannelIds, maximumParameters->maxChannelIds);
557 if (targetParameters->maxUserIds >= 3)
559 pOutParameters->maxUserIds = targetParameters->maxUserIds;
561 else if (maximumParameters->maxUserIds >= 3)
563 pOutParameters->maxUserIds = 3;
567 WLog_Print(log, WLOG_ERROR,
"invalid maxUserIds [%" PRIu32
", %" PRIu32
"]",
568 targetParameters->maxUserIds, maximumParameters->maxUserIds);
573 pOutParameters->maxTokenIds = targetParameters->maxTokenIds;
577 if (minimumParameters->numPriorities <= 1)
579 pOutParameters->numPriorities = 1;
583 WLog_Print(log, WLOG_ERROR,
"invalid numPriorities [%" PRIu32
"]",
584 maximumParameters->numPriorities);
589 pOutParameters->minThroughput = targetParameters->minThroughput;
593 if ((targetParameters->maxHeight == 1) || (minimumParameters->maxHeight <= 1))
595 pOutParameters->maxHeight = 1;
599 WLog_Print(log, WLOG_ERROR,
"invalid maxHeight [%" PRIu32
", %" PRIu32
"]",
600 targetParameters->maxHeight, minimumParameters->maxHeight);
606 if (targetParameters->maxMCSPDUsize >= 1024)
608 if (targetParameters->maxMCSPDUsize <= 65528)
610 pOutParameters->maxMCSPDUsize = targetParameters->maxMCSPDUsize;
612 else if ((minimumParameters->maxMCSPDUsize >= 124) &&
613 (minimumParameters->maxMCSPDUsize <= 65528))
615 pOutParameters->maxMCSPDUsize = 65528;
619 WLog_Print(log, WLOG_ERROR,
"invalid maxMCSPDUsize [%" PRIu32
", %" PRIu32
"]",
620 targetParameters->maxMCSPDUsize, minimumParameters->maxMCSPDUsize);
626 if (maximumParameters->maxMCSPDUsize >= 124)
628 pOutParameters->maxMCSPDUsize = maximumParameters->maxMCSPDUsize;
632 WLog_Print(log, WLOG_ERROR,
"invalid maxMCSPDUsize [%" PRIu32
"]",
633 maximumParameters->maxMCSPDUsize);
640 if ((targetParameters->protocolVersion == 2) ||
641 ((minimumParameters->protocolVersion <= 2) && (maximumParameters->protocolVersion >= 2)))
643 pOutParameters->protocolVersion = 2;
647 WLog_Print(log, WLOG_ERROR,
648 "invalid protocolVersion [%" PRIu32
", %" PRIu32
", %" PRIu32
"]",
649 targetParameters->protocolVersion, minimumParameters->protocolVersion,
650 maximumParameters->protocolVersion);
664BOOL mcs_recv_connect_initial(rdpMcs* mcs,
wStream* s)
668 BOOL upwardFlag = FALSE;
674 if (!tpkt_read_header(s, &tlength))
677 if (!tpdu_read_data(s, &li, tlength))
680 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
684 if (!ber_read_octet_string_tag(s, &length) ||
685 (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length)))
688 Stream_Seek(s, length);
691 if (!ber_read_octet_string_tag(s, &length) ||
692 (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length)))
695 Stream_Seek(s, length);
698 if (!ber_read_BOOL(s, &upwardFlag))
702 if (!mcs_read_domain_parameters(s, &mcs->targetParameters))
706 if (!mcs_read_domain_parameters(s, &mcs->minimumParameters))
710 if (!mcs_read_domain_parameters(s, &mcs->maximumParameters))
713 if (!ber_read_octet_string_tag(s, &length) ||
714 (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length)))
717 if (!gcc_read_conference_create_request(s, mcs))
720 if (!mcs_merge_domain_parameters(mcs->log, &mcs->targetParameters, &mcs->minimumParameters,
721 &mcs->maximumParameters, &mcs->domainParameters))
724 return tpkt_ensure_stream_consumed(mcs->log, s, tlength);
735BOOL mcs_write_connect_initial(
wStream* s, rdpMcs* mcs,
wStream* userData)
741 if (!s || !mcs || !userData)
744 tmps = Stream_New(
nullptr, Stream_Capacity(s));
748 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
753 if (!ber_write_octet_string(tmps, callingDomainSelector,
sizeof(callingDomainSelector)))
756 if (!ber_write_octet_string(tmps, calledDomainSelector,
sizeof(calledDomainSelector)))
759 ber_write_BOOL(tmps, TRUE);
762 if (!mcs_write_domain_parameters(mcs->log, tmps, &mcs->targetParameters))
766 if (!mcs_write_domain_parameters(mcs->log, tmps, &mcs->minimumParameters))
770 if (!mcs_write_domain_parameters(mcs->log, tmps, &mcs->maximumParameters))
774 if (!ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData)))
776 length = Stream_GetPosition(tmps);
778 ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length);
779 Stream_Write(s, Stream_Buffer(tmps), length);
782 Stream_Free(tmps, TRUE);
796BOOL mcs_write_connect_response(
wStream* s, rdpMcs* mcs,
wStream* userData)
802 if (!s || !mcs || !userData)
805 tmps = Stream_New(
nullptr, Stream_Capacity(s));
809 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
813 ber_write_enumerated(tmps, 0, MCS_Result_enum_length);
814 if (!ber_write_integer(tmps, 0))
817 if (!mcs_write_domain_parameters(mcs->log, tmps, &(mcs->domainParameters)))
821 if (!ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData)))
823 length = Stream_GetPosition(tmps);
824 ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
825 Stream_Write(s, Stream_Buffer(tmps), length);
828 Stream_Free(tmps, TRUE);
838static BOOL mcs_send_connect_initial(rdpMcs* mcs)
847 if (!mcs || !mcs->context)
850 mcs_initialize_client_channels(mcs, mcs->context->settings);
851 wStream* client_data = Stream_New(
nullptr, 512);
855 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
859 if (!gcc_write_client_data_blocks(client_data, mcs))
861 gcc_CCrq = Stream_New(
nullptr, 1024);
865 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
869 if (!gcc_write_conference_create_request(gcc_CCrq, client_data))
871 length = Stream_GetPosition(gcc_CCrq) + 7;
872 s = Stream_New(
nullptr, 1024 + length);
876 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
880 bm = Stream_GetPosition(s);
883 if (!mcs_write_connect_initial(s, mcs, gcc_CCrq))
885 WLog_Print(mcs->log, WLOG_ERROR,
"mcs_write_connect_initial failed!");
889 em = Stream_GetPosition(s);
891 if (length > UINT16_MAX)
893 if (!Stream_SetPosition(s, bm))
895 if (!tpkt_write_header(s, (UINT16)length))
897 if (!tpdu_write_data(s))
899 if (!Stream_SetPosition(s, em))
901 Stream_SealLength(s);
904 rdpTransport* transport = freerdp_get_transport(mcs->context);
905 status = transport_write(transport, s);
909 Stream_Free(s, TRUE);
910 Stream_Free(gcc_CCrq, TRUE);
911 Stream_Free(client_data, TRUE);
912 return ((status >= 0));
921BOOL mcs_recv_connect_response(rdpMcs* mcs,
wStream* s)
927 UINT32 calledConnectId = 0;
932 if (!tpkt_read_header(s, &tlength))
935 if (!tpdu_read_data(s, &li, tlength))
938 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length) ||
939 !ber_read_enumerated(s, &result, MCS_Result_enum_length) ||
940 !ber_read_integer(s, &calledConnectId) ||
941 !mcs_read_domain_parameters(s, &(mcs->domainParameters)) ||
942 !ber_read_octet_string_tag(s, &length))
947 if (!gcc_read_conference_create_response(s, mcs))
949 WLog_Print(mcs->log, WLOG_ERROR,
"gcc_read_conference_create_response failed");
953 return tpkt_ensure_stream_consumed(mcs->log, s, tlength);
962BOOL mcs_send_connect_response(rdpMcs* mcs)
974 wStream* server_data = Stream_New(
nullptr, 512);
978 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
982 if (!gcc_write_server_data_blocks(server_data, mcs))
985 gcc_CCrsp = Stream_New(
nullptr, 512 + Stream_Capacity(server_data));
989 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
993 if (!gcc_write_conference_create_response(gcc_CCrsp, server_data))
995 length = Stream_GetPosition(gcc_CCrsp) + 7;
996 s = Stream_New(
nullptr, length + 1024);
1000 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
1004 bm = Stream_GetPosition(s);
1007 if (!mcs_write_connect_response(s, mcs, gcc_CCrsp))
1010 em = Stream_GetPosition(s);
1012 if (length > UINT16_MAX)
1014 if (!Stream_SetPosition(s, bm))
1016 if (!tpkt_write_header(s, (UINT16)length))
1018 if (!tpdu_write_data(s))
1020 if (!Stream_SetPosition(s, em))
1022 Stream_SealLength(s);
1025 rdpTransport* transport = freerdp_get_transport(mcs->context);
1026 status = transport_write(transport, s);
1030 Stream_Free(s, TRUE);
1031 Stream_Free(gcc_CCrsp, TRUE);
1032 Stream_Free(server_data, TRUE);
1033 return (status >= 0);
1043BOOL mcs_recv_erect_domain_request(rdpMcs* mcs,
wStream* s)
1046 UINT32 subHeight = 0;
1047 UINT32 subInterval = 0;
1052 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_ErectDomainRequest, &length,
1056 if (!per_read_integer(s, &subHeight))
1059 if (!per_read_integer(s, &subInterval))
1062 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1071BOOL mcs_send_erect_domain_request(rdpMcs* mcs)
1079 wStream* s = Stream_New(
nullptr, length);
1083 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
1087 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0))
1089 if (!per_write_integer(s, 0))
1091 if (!per_write_integer(s, 0))
1093 Stream_SealLength(s);
1095 rdpTransport* transport = freerdp_get_transport(mcs->context);
1096 status = transport_write(transport, s);
1098 Stream_Free(s, TRUE);
1099 return (status >= 0);
1109BOOL mcs_recv_attach_user_request(rdpMcs* mcs,
wStream* s)
1116 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_AttachUserRequest, &length,
1119 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1128BOOL mcs_send_attach_user_request(rdpMcs* mcs)
1136 wStream* s = Stream_New(
nullptr, length);
1140 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
1144 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0))
1147 Stream_SealLength(s);
1149 rdpTransport* transport = freerdp_get_transport(mcs->context);
1150 status = transport_write(transport, s);
1153 Stream_Free(s, TRUE);
1154 return (status >= 0);
1163BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs,
wStream* s)
1171 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_AttachUserConfirm, &length,
1174 if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
1176 if (!per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID))
1178 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1187BOOL mcs_send_attach_user_confirm(rdpMcs* mcs)
1195 wStream* s = Stream_New(
nullptr, length);
1199 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
1203 mcs->userId = mcs->baseChannelId++;
1204 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2))
1206 if (!per_write_enumerated(s, 0, MCS_Result_enum_length))
1208 if (!per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID))
1210 Stream_SealLength(s);
1212 rdpTransport* transport = freerdp_get_transport(mcs->context);
1213 status = transport_write(transport, s);
1215 Stream_Free(s, TRUE);
1216 return (status >= 0);
1226BOOL mcs_recv_channel_join_request(rdpMcs* mcs,
const rdpSettings* settings,
wStream* s,
1232 if (!mcs || !s || !channelId)
1235 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_ChannelJoinRequest, &length,
1239 if (!per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID))
1241 if (userId != mcs->userId)
1244 mcs->userId = userId;
1248 if (!per_read_integer16(s, channelId, 0))
1251 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1264BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId)
1271 wStream* s = Stream_New(
nullptr, length);
1275 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
1279 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0))
1281 if (!per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID))
1283 if (!per_write_integer16(s, channelId, 0))
1285 Stream_SealLength(s);
1287 rdpTransport* transport = freerdp_get_transport(mcs->context);
1288 status = transport_write(transport, s);
1291 Stream_Free(s, TRUE);
1292 return (status >= 0);
1301BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs,
wStream* s, UINT16* channelId)
1305 UINT16 initiator = 0;
1306 UINT16 requested = 0;
1309 WINPR_ASSERT(channelId);
1311 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_ChannelJoinConfirm, &length,
1315 if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
1317 if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID))
1319 if (!per_read_integer16(s, &requested, 0))
1321 if (!per_read_integer16(s, channelId, 0))
1323 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1332BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId)
1340 wStream* s = Stream_New(
nullptr, length);
1344 WLog_Print(mcs->log, WLOG_ERROR,
"Stream_New failed!");
1348 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2))
1350 if (!per_write_enumerated(s, 0, MCS_Result_enum_length))
1352 if (!per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID))
1354 if (!per_write_integer16(s, channelId, 0))
1356 if (!per_write_integer16(s, channelId, 0))
1358 Stream_SealLength(s);
1361 rdpTransport* transport = freerdp_get_transport(mcs->context);
1362 status = transport_write(transport, s);
1366 Stream_Free(s, TRUE);
1367 return (status >= 0);
1375BOOL mcs_recv_disconnect_provider_ultimatum(WINPR_ATTR_UNUSED rdpMcs* mcs,
wStream* s,
int* reason)
1382 WINPR_ASSERT(reason);
1411 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 1))
1414 Stream_Rewind_UINT8(s);
1415 Stream_Read_UINT8(s, b1);
1416 Stream_Read_UINT8(s, b2);
1417 *reason = ((b1 & 0x01) << 1) | (b2 >> 7);
1426BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs,
enum Disconnect_Ultimatum reason)
1433 wStream* s = Stream_New(
nullptr, length);
1438 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1))
1441 if (!per_write_enumerated(s, 0x80, WINPR_ASSERTING_INT_CAST(BYTE, reason)))
1445 rdpTransport* transport = freerdp_get_transport(mcs->context);
1446 status = transport_write(transport, s);
1450 WLog_Print(mcs->log, WLOG_DEBUG,
"sending DisconnectProviderUltimatum(%s)",
1451 freerdp_disconnect_reason_string((
int)reason));
1452 Stream_Free(s, TRUE);
1453 return (status >= 0);
1456BOOL mcs_client_begin(rdpMcs* mcs)
1458 if (!mcs || !mcs->context)
1462 if (!mcs_send_connect_initial(mcs))
1464 freerdp_set_last_error_if_not(mcs->context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
1466 WLog_Print(mcs->log, WLOG_ERROR,
"Error: unable to send MCS Connect Initial");
1479rdpMcs* mcs_new(rdpContext* context)
1481 rdpMcs* mcs = (rdpMcs*)calloc(1,
sizeof(rdpMcs));
1485 mcs->log = WLog_Get(MCS_TAG);
1486 WINPR_ASSERT(mcs->log);
1488 mcs->context = context;
1489 mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF);
1490 mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420);
1491 mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF);
1492 mcs_init_domain_parameters(&mcs->domainParameters, 0, 0, 0, 0xFFFF);
1493 mcs->channelCount = 0;
1494 mcs->channelMaxCount = CHANNEL_MAX_COUNT;
1495 mcs->baseChannelId = MCS_GLOBAL_CHANNEL_ID + 1;
1496 mcs->channels = (rdpMcsChannel*)calloc(mcs->channelMaxCount,
sizeof(rdpMcsChannel));
1512void mcs_free(rdpMcs* mcs)
1516 free(mcs->channels);
1521BOOL mcs_server_apply_to_settings(
const rdpMcs* mcs, rdpSettings* settings)
1526 WINPR_ASSERT(settings);
1531 for (UINT32 x = 0; x < mcs->channelCount; x++)
1533 const rdpMcsChannel* current = &mcs->channels[x];
1535 def.options = current->options;
1536 memcpy(def.name, current->Name,
sizeof(def.name));
1537 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_ChannelDefArray, x, &def))
1544 WLog_Print(mcs->log, WLOG_WARN,
"failed to apply settings");
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.