2 * FreeRDP: A Remote Desktop Protocol Client
3 * T.125 Multipoint Communication Service (MCS) Protocol
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
27 * T.125 MCS is defined in:
29 * http://www.itu.int/rec/T-REC-T.125-199802-I/
30 * ITU-T T.125 Multipoint Communication Service Protocol Specification
34 * Connect-Initial ::= [APPLICATION 101] IMPLICIT SEQUENCE
36 * callingDomainSelector OCTET_STRING,
37 * calledDomainSelector OCTET_STRING,
39 * targetParameters DomainParameters,
40 * minimumParameters DomainParameters,
41 * maximumParameters DomainParameters,
42 * userData OCTET_STRING
45 * DomainParameters ::= SEQUENCE
47 * maxChannelIds INTEGER (0..MAX),
48 * maxUserIds INTEGER (0..MAX),
49 * maxTokenIds INTEGER (0..MAX),
50 * numPriorities INTEGER (0..MAX),
51 * minThroughput INTEGER (0..MAX),
52 * maxHeight INTEGER (0..MAX),
53 * maxMCSPDUsize INTEGER (0..MAX),
54 * protocolVersion INTEGER (0..MAX)
57 * Connect-Response ::= [APPLICATION 102] IMPLICIT SEQUENCE
60 * calledConnectId INTEGER (0..MAX),
61 * domainParameters DomainParameters,
62 * userData OCTET_STRING
65 * Result ::= ENUMERATED
68 * rt-domain-merging (1),
69 * rt-domain-not-hierarchical (2),
70 * rt-no-such-channel (3),
71 * rt-no-such-domain (4),
72 * rt-no-such-user (5),
73 * rt-not-admitted (6),
74 * rt-other-user-id (7),
75 * rt-parameters-unacceptable (8),
76 * rt-token-not-available (9),
77 * rt-token-not-possessed (10),
78 * rt-too-many-channels (11),
79 * rt-too-many-tokens (12),
80 * rt-too-many-users (13),
81 * rt-unspecified-failure (14),
82 * rt-user-rejected (15)
85 * ErectDomainRequest ::= [APPLICATION 1] IMPLICIT SEQUENCE
87 * subHeight INTEGER (0..MAX),
88 * subInterval INTEGER (0..MAX)
91 * AttachUserRequest ::= [APPPLICATION 10] IMPLICIT SEQUENCE
95 * AttachUserConfirm ::= [APPLICATION 11] IMPLICIT SEQUENCE
98 * initiator UserId OPTIONAL
101 * ChannelJoinRequest ::= [APPLICATION 14] IMPLICIT SEQUENCE
104 * channelId ChannelId
107 * ChannelJoinConfirm ::= [APPLICATION 15] IMPLICIT SEQUENCE
111 * requested ChannelId,
112 * channelId ChannelId OPTIONAL
115 * SendDataRequest ::= [APPLICATION 25] IMPLICIT SEQUENCE
118 * channelId ChannelId,
119 * dataPriority DataPriority,
120 * segmentation Segmentation,
121 * userData OCTET_STRING
124 * DataPriority ::= CHOICE
133 * Segmentation ::= BIT_STRING
139 * SendDataIndication ::= SEQUENCE
142 * channelId ChannelId,
143 * reliability BOOLEAN,
144 * domainReferenceID INTEGER (0..65535) OPTIONAL,
145 * dataPriority DataPriority,
146 * segmentation Segmentation,
147 * userData OCTET_STRING,
148 * totalDataSize INTEGER OPTIONAL,
149 * nonStandard SEQUENCE OF NonStandardParameter OPTIONAL,
155 static const uint8 callingDomainSelector[1] = "\x01";
156 static const uint8 calledDomainSelector[1] = "\x01";
159 static const char* const mcs_result_enumerated[] =
163 "rt-domain-not-hierarchical",
164 "rt-no-such-channel",
169 "rt-parameters-unacceptable",
170 "rt-token-not-available",
171 "rt-token-not-possessed",
172 "rt-too-many-channels",
173 "rt-too-many-tokens",
175 "rt-unspecified-failure",
181 * Read a DomainMCSPDU header.
183 * @param domainMCSPDU DomainMCSPDU type
184 * @param length TPKT length
188 boolean mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, uint16* length)
191 enum DomainMCSPDU MCSPDU;
193 *length = tpkt_read_header(s);
195 if (tpdu_read_data(s) == 0)
198 MCSPDU = *domainMCSPDU;
199 per_read_choice(s, &choice);
200 *domainMCSPDU = (choice >> 2);
202 if (*domainMCSPDU != MCSPDU)
209 * Write a DomainMCSPDU header.
211 * @param domainMCSPDU DomainMCSPDU type
212 * @param length TPKT length
215 void mcs_write_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU domainMCSPDU, uint16 length, uint8 options)
217 tpkt_write_header(s, length);
219 per_write_choice(s, (domainMCSPDU << 2) | options);
223 * Initialize MCS Domain Parameters.
224 * @param domainParameters domain parameters
225 * @param maxChannelIds max channel ids
226 * @param maxUserIds max user ids
227 * @param maxTokenIds max token ids
228 * @param maxMCSPDUsize max MCS PDU size
231 static void mcs_init_domain_parameters(DomainParameters* domainParameters,
232 uint32 maxChannelIds, uint32 maxUserIds, uint32 maxTokenIds, uint32 maxMCSPDUsize)
234 domainParameters->maxChannelIds = maxChannelIds;
235 domainParameters->maxUserIds = maxUserIds;
236 domainParameters->maxTokenIds = maxTokenIds;
237 domainParameters->maxMCSPDUsize = maxMCSPDUsize;
239 domainParameters->numPriorities = 1;
240 domainParameters->minThroughput = 0;
241 domainParameters->maxHeight = 1;
242 domainParameters->protocolVersion = 2;
246 * Read MCS Domain Parameters.
248 * @param domainParameters domain parameters
251 boolean mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParameters)
254 ber_read_sequence_tag(s, &length);
255 ber_read_integer(s, &(domainParameters->maxChannelIds));
256 ber_read_integer(s, &(domainParameters->maxUserIds));
257 ber_read_integer(s, &(domainParameters->maxTokenIds));
258 ber_read_integer(s, &(domainParameters->numPriorities));
259 ber_read_integer(s, &(domainParameters->minThroughput));
260 ber_read_integer(s, &(domainParameters->maxHeight));
261 ber_read_integer(s, &(domainParameters->maxMCSPDUsize));
262 ber_read_integer(s, &(domainParameters->protocolVersion));
268 * Write MCS Domain Parameters.
270 * @param domainParameters domain parameters
273 void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParameters)
278 tmps = stream_new(stream_get_size(s));
279 ber_write_integer(tmps, domainParameters->maxChannelIds);
280 ber_write_integer(tmps, domainParameters->maxUserIds);
281 ber_write_integer(tmps, domainParameters->maxTokenIds);
282 ber_write_integer(tmps, domainParameters->numPriorities);
283 ber_write_integer(tmps, domainParameters->minThroughput);
284 ber_write_integer(tmps, domainParameters->maxHeight);
285 ber_write_integer(tmps, domainParameters->maxMCSPDUsize);
286 ber_write_integer(tmps, domainParameters->protocolVersion);
288 length = stream_get_length(tmps);
289 ber_write_sequence_tag(s, length);
290 stream_write(s, stream_get_head(tmps), length);
295 * Print MCS Domain Parameters.
296 * @param domainParameters domain parameters
299 void mcs_print_domain_parameters(DomainParameters* domainParameters)
301 printf("DomainParameters {\n");
302 printf("\tmaxChannelIds:%d\n", domainParameters->maxChannelIds);
303 printf("\tmaxUserIds:%d\n", domainParameters->maxUserIds);
304 printf("\tmaxTokenIds:%d\n", domainParameters->maxTokenIds);
305 printf("\tnumPriorities:%d\n", domainParameters->numPriorities);
306 printf("\tminThroughput:%d\n", domainParameters->minThroughput);
307 printf("\tmaxHeight:%d\n", domainParameters->maxHeight);
308 printf("\tmaxMCSPDUsize:%d\n", domainParameters->maxMCSPDUsize);
309 printf("\tprotocolVersion:%d\n", domainParameters->protocolVersion);
314 * Read an MCS Connect Initial PDU.\n
316 * @param mcs MCS module
320 boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s)
327 if (tpdu_read_data(s) == 0)
330 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
333 /* callingDomainSelector (OCTET_STRING) */
334 if (!ber_read_octet_string(s, &length))
336 stream_seek(s, length);
338 /* calledDomainSelector (OCTET_STRING) */
339 if (!ber_read_octet_string(s, &length))
341 stream_seek(s, length);
343 /* upwardFlag (BOOLEAN) */
344 if (!ber_read_boolean(s, &upwardFlag))
347 /* targetParameters (DomainParameters) */
348 mcs_read_domain_parameters(s, &mcs->targetParameters);
350 /* minimumParameters (DomainParameters) */
351 mcs_read_domain_parameters(s, &mcs->minimumParameters);
353 /* maximumParameters (DomainParameters) */
354 mcs_read_domain_parameters(s, &mcs->maximumParameters);
356 if (!ber_read_octet_string(s, &length))
359 if (!gcc_read_conference_create_request(s, mcs->transport->settings))
366 * Write an MCS Connect Initial PDU.\n
369 * @param mcs MCS module
370 * @param user_data GCC Conference Create Request
373 void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data)
378 tmps = stream_new(stream_get_size(s));
380 /* callingDomainSelector (OCTET_STRING) */
381 ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector));
383 /* calledDomainSelector (OCTET_STRING) */
384 ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector));
386 /* upwardFlag (BOOLEAN) */
387 ber_write_boolean(tmps, true);
389 /* targetParameters (DomainParameters) */
390 mcs_write_domain_parameters(tmps, &mcs->targetParameters);
392 /* minimumParameters (DomainParameters) */
393 mcs_write_domain_parameters(tmps, &mcs->minimumParameters);
395 /* maximumParameters (DomainParameters) */
396 mcs_write_domain_parameters(tmps, &mcs->maximumParameters);
398 /* userData (OCTET_STRING) */
399 ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data));
401 length = stream_get_length(tmps);
402 /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */
403 ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length);
404 stream_write(s, stream_get_head(tmps), length);
409 * Write an MCS Connect Response PDU.\n
412 * @param mcs MCS module
413 * @param user_data GCC Conference Create Response
416 void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data)
421 tmps = stream_new(stream_get_size(s));
422 ber_write_enumerated(tmps, 0, MCS_Result_enum_length);
423 ber_write_integer(tmps, 0); /* calledConnectId */
424 mcs->domainParameters = mcs->targetParameters;
425 mcs_write_domain_parameters(tmps, &(mcs->domainParameters));
426 /* userData (OCTET_STRING) */
427 ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data));
429 length = stream_get_length(tmps);
430 ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
431 stream_write(s, stream_get_head(tmps), length);
436 * Send MCS Connect Initial.\n
438 * @param mcs mcs module
441 boolean mcs_send_connect_initial(rdpMcs* mcs)
450 client_data = stream_new(512);
451 gcc_write_client_data_blocks(client_data, mcs->transport->settings);
453 gcc_CCrq = stream_new(512);
454 gcc_write_conference_create_request(gcc_CCrq, client_data);
455 length = stream_get_length(gcc_CCrq) + 7;
457 s = transport_send_stream_init(mcs->transport, 1024);
458 stream_get_mark(s, bm);
461 mcs_write_connect_initial(s, mcs, gcc_CCrq);
462 stream_get_mark(s, em);
464 stream_set_mark(s, bm);
466 tpkt_write_header(s, length);
468 stream_set_mark(s, em);
470 status = transport_write(mcs->transport, s);
472 stream_free(gcc_CCrq);
473 stream_free(client_data);
475 return (status < 0 ? false : true);
479 * Read MCS Connect Response.\n
481 * @param mcs mcs module
484 boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s)
488 uint32 calledConnectId;
492 if (tpdu_read_data(s) == 0)
495 ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length);
496 ber_read_enumerated(s, &result, MCS_Result_enum_length);
497 ber_read_integer(s, &calledConnectId);
499 if (!mcs_read_domain_parameters(s, &(mcs->domainParameters)))
502 ber_read_octet_string(s, &length);
504 if (!gcc_read_conference_create_response(s, mcs->transport->settings))
506 printf("mcs_recv_connect_response: gcc_read_conference_create_response failed\n");
514 * Send MCS Connect Response.\n
516 * @param mcs mcs module
519 boolean mcs_send_connect_response(rdpMcs* mcs)
527 server_data = stream_new(512);
528 gcc_write_server_data_blocks(server_data, mcs->transport->settings);
530 gcc_CCrsp = stream_new(512);
531 gcc_write_conference_create_response(gcc_CCrsp, server_data);
532 length = stream_get_length(gcc_CCrsp) + 7;
534 s = transport_send_stream_init(mcs->transport, 1024);
535 stream_get_mark(s, bm);
538 mcs_write_connect_response(s, mcs, gcc_CCrsp);
539 stream_get_mark(s, em);
541 stream_set_mark(s, bm);
543 tpkt_write_header(s, length);
545 stream_set_mark(s, em);
547 transport_write(mcs->transport, s);
549 stream_free(gcc_CCrsp);
550 stream_free(server_data);
556 * Read MCS Erect Domain Request.\n
562 boolean mcs_recv_erect_domain_request(rdpMcs* mcs, STREAM* s)
565 enum DomainMCSPDU MCSPDU;
567 MCSPDU = DomainMCSPDU_ErectDomainRequest;
568 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
575 * Send MCS Erect Domain Request.\n
580 boolean mcs_send_erect_domain_request(rdpMcs* mcs)
584 s = transport_send_stream_init(mcs->transport, length);
586 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0);
588 per_write_integer(s, 0); /* subHeight (INTEGER) */
589 per_write_integer(s, 0); /* subInterval (INTEGER) */
591 if (transport_write(mcs->transport, s) < 0)
598 * Read MCS Attach User Request.\n
600 * @param mcs mcs module
604 boolean mcs_recv_attach_user_request(rdpMcs* mcs, STREAM* s)
607 enum DomainMCSPDU MCSPDU;
609 MCSPDU = DomainMCSPDU_AttachUserRequest;
610 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
617 * Send MCS Attach User Request.\n
619 * @param mcs mcs module
622 boolean mcs_send_attach_user_request(rdpMcs* mcs)
626 s = transport_send_stream_init(mcs->transport, length);
628 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0);
630 if (transport_write(mcs->transport, s) < 0)
637 * Read MCS Attach User Confirm.\n
639 * @param mcs mcs module
642 boolean mcs_recv_attach_user_confirm(rdpMcs* mcs, STREAM* s)
646 enum DomainMCSPDU MCSPDU;
648 MCSPDU = DomainMCSPDU_AttachUserConfirm;
649 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
652 per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */
653 per_read_integer16(s, &(mcs->user_id), MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
659 * Send MCS Attach User Confirm.\n
661 * @param mcs mcs module
664 boolean mcs_send_attach_user_confirm(rdpMcs* mcs)
669 s = transport_send_stream_init(mcs->transport, length);
671 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2);
673 per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */
675 per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
677 transport_write(mcs->transport, s);
683 * Read MCS Channel Join Request.\n
685 * @param mcs mcs module
689 boolean mcs_recv_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id)
692 enum DomainMCSPDU MCSPDU;
695 MCSPDU = DomainMCSPDU_ChannelJoinRequest;
696 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
699 if (!per_read_integer16(s, &user_id, MCS_BASE_CHANNEL_ID))
701 if (user_id != mcs->user_id)
703 if (!per_read_integer16(s, channel_id, 0))
710 * Send MCS Channel Join Request.\n
712 * @param mcs mcs module
713 * @param channel_id channel id
716 boolean mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id)
720 s = transport_send_stream_init(mcs->transport, 12);
722 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0);
724 per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID);
725 per_write_integer16(s, channel_id, 0);
727 if (transport_write(mcs->transport, s) < 0)
734 * Read MCS Channel Join Confirm.\n
736 * @param mcs mcs module
739 boolean mcs_recv_channel_join_confirm(rdpMcs* mcs, STREAM* s, uint16* channel_id)
745 enum DomainMCSPDU MCSPDU;
747 MCSPDU = DomainMCSPDU_ChannelJoinConfirm;
748 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
751 per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */
752 per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
753 per_read_integer16(s, &requested, 0); /* requested (ChannelId) */
754 per_read_integer16(s, channel_id, 0); /* channelId */
760 * Send MCS Channel Join Confirm.\n
762 * @param mcs mcs module
765 boolean mcs_send_channel_join_confirm(rdpMcs* mcs, uint16 channel_id)
769 s = transport_send_stream_init(mcs->transport, 15);
771 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2);
773 per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */
774 per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
775 per_write_integer16(s, channel_id, 0); /* requested (ChannelId) */
776 per_write_integer16(s, channel_id, 0); /* channelId */
778 transport_write(mcs->transport, s);
784 * Send MCS Disconnect Provider Ultimatum PDU.\n
785 * @param mcs mcs module
788 boolean mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs)
792 s = transport_send_stream_init(mcs->transport, 9);
794 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1);
796 per_write_enumerated(s, 0, 0); /* reason */
798 transport_write(mcs->transport, s);
804 * Instantiate new MCS module.
805 * @param transport transport
806 * @return new MCS module
809 rdpMcs* mcs_new(rdpTransport* transport)
813 mcs = (rdpMcs*) xzalloc(sizeof(rdpMcs));
817 mcs->transport = transport;
818 mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF);
819 mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420);
820 mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF);
828 * @param mcs MCS module to be freed
831 void mcs_free(rdpMcs* mcs)