{
add_test_suite(gcc);
- add_test_function(gcc_write_create_conference_request);
+ add_test_function(gcc_write_conference_create_request);
add_test_function(gcc_write_client_core_data);
add_test_function(gcc_write_client_security_data);
add_test_function(gcc_write_client_cluster_data);
"\x00\x00\x80\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0"
"\x72\x64\x70\x73\x6e\x64\x00\x00\x00\x00\x00\xc0";
-uint8 gcc_create_conference_request_expected[307] =
+uint8 gcc_conference_create_request_expected[307] =
"\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00\x08\x00\x10\x00\x01\xC0"
"\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8\x00\x04\x00\x08\x00\x00"
"\x05\x00\x04\x01\xCA\x03\xAA\x09\x04\x00\x00\xCE\x0E\x00\x00\x45"
"\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70\x73\x6e\x64\x00\x00\x00"
"\x00\x00\xc0";
-void test_gcc_write_create_conference_request(void)
+void test_gcc_write_conference_create_request(void)
{
STREAM* s;
STREAM user_data;
user_data.size = sizeof(gcc_user_data);
user_data.p = user_data.data + user_data.size;
- s = stream_new(sizeof(gcc_create_conference_request_expected));
+ s = stream_new(sizeof(gcc_conference_create_request_expected));
- gcc_write_create_conference_request(s, &user_data);
- ASSERT_STREAM(s, (uint8*) gcc_create_conference_request_expected, sizeof(gcc_create_conference_request_expected));
+ gcc_write_conference_create_request(s, &user_data);
+ ASSERT_STREAM(s, (uint8*) gcc_conference_create_request_expected, sizeof(gcc_conference_create_request_expected));
}
uint8 gcc_client_core_data_expected[216] =
int clean_gcc_suite(void);
int add_gcc_suite(void);
-void test_gcc_write_create_conference_request(void);
+void test_gcc_write_conference_create_request(void);
void test_gcc_write_client_core_data(void);
void test_gcc_write_client_security_data(void);
void test_gcc_write_client_cluster_data(void);
* conferenceMode ConferenceMode OPTIONAL
* }
*
+ * ConferenceCreateResponse ::= SEQUENCE
+ * {
+ * nodeID UserID,
+ * tag INTEGER,
+ * result ENUMERATED
+ * {
+ * success (0),
+ * userRejected (1),
+ * resourcesNotAvailable (2),
+ * rejectedForSymmetryBreaking (3),
+ * lockedConferenceNotSupported (4)
+ * },
+ * userData UserData OPTIONAL,
+ * ...
+ * }
+ *
* ConferenceName ::= SEQUENCE
* {
* numeric SimpleNumericString
*
* H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255))
*
+ * UserID ::= DynamicChannelID
+ *
+ * ChannelID ::= INTEGER (1..65535)
+ * StaticChannelID ::= INTEGER (1..1000)
+ * DynamicChannelID ::= INTEGER (1001..65535)
+ *
*/
/*
*/
uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
+uint8 h221_cs_key[4] = "Duca";
+uint8 h221_sc_key[4] = "McDn";
+
/**
* Write a GCC Conference Create Request.\n
* @msdn{cc240836}
* @param user_data client data blocks
*/
-void gcc_write_create_conference_request(STREAM* s, STREAM* user_data)
+void gcc_write_conference_create_request(STREAM* s, STREAM* user_data)
{
/* ConnectData */
per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */
per_write_choice(s, 0xC0); /* UserData::value present + select h221NonStandard (1) */
/* h221NonStandard */
- per_write_octet_string(s, "Duca", 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
+ per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
/* userData::value (OCTET_STRING) */
per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of client data blocks */
}
+void gcc_read_conference_create_response(STREAM* s)
+{
+ int length;
+ uint32 tag;
+ uint16 nodeID;
+ uint8 result;
+ uint8 choice;
+ uint8 selection;
+ uint8 number;
+
+ /* ConnectData */
+ per_read_choice(s, &choice);
+ per_read_object_identifier(s, t124_02_98_oid);
+
+ /* ConnectData::connectPDU (OCTET_STRING) */
+ per_read_length(s, &length);
+
+ /* ConnectGCCPDU */
+ per_read_choice(s, &choice);
+
+ /* ConferenceCreateResponse::nodeID (UserID) */
+ per_read_integer16(s, &nodeID, 1001);
+
+ /* ConferenceCreateResponse::tag (INTEGER) */
+ per_read_integer(s, &tag);
+
+ /* ConferenceCreateResponse::result (ENUMERATED) */
+ per_read_enumerated(s, &result);
+
+ /* number of UserData sets */
+ per_read_number_of_sets(s, &number);
+
+ /* UserData::value present + select h221NonStandard (1) */
+ per_read_choice(s, &choice);
+
+ /* h221NonStandard */
+ per_read_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
+
+ /* userData (OCTET_STRING) */
+ per_read_length(s, &length);
+
+ printf("server core data, length:%d\n", length);
+}
+
/**
* Write a user data header (TS_UD_HEADER).\n
* @msdn{cc240509}
/* Monitor Flags */
#define MONITOR_PRIMARY 0x00000001
-void gcc_write_create_conference_request(STREAM* s, STREAM* user_data);
+void gcc_write_conference_create_request(STREAM* s, STREAM* user_data);
+void gcc_read_conference_create_response(STREAM* s);
void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length);
void gcc_write_client_core_data(STREAM* s, rdpSettings *settings);
gcc_write_client_monitor_data(client_data, mcs->transport->settings);
gcc_CCrq = stream_new(512);
- gcc_write_create_conference_request(gcc_CCrq, client_data);
+ gcc_write_conference_create_request(gcc_CCrq, client_data);
length = stream_get_length(gcc_CCrq) + 7;
s = stream_new(512);
ber_read_octet_string(s, &length);
- printf("userData, length:%d\n", length);
+ gcc_read_conference_create_response(s);
}
/**
#include "per.h"
+boolean per_read_length(STREAM* s, int* length)
+{
+ uint8 byte;
+
+ stream_read_uint8(s, byte);
+
+ if (byte & 0x80)
+ {
+ *length = (byte << 8);
+ stream_read_uint8(s, byte);
+ *length += byte;
+ }
+ else
+ {
+ *length = byte;
+ }
+
+ return True;
+}
+
/**
* Write PER length.
* @param s stream
stream_write_uint8(s, length);
}
+boolean per_read_choice(STREAM* s, uint8* choice)
+{
+ stream_read_uint8(s, *choice);
+ return True;
+}
+
/**
* Write PER CHOICE.
* @param s stream
stream_write_uint8(s, choice);
}
+boolean per_read_selection(STREAM* s, uint8* selection)
+{
+ stream_read_uint8(s, *selection);
+ return True;
+}
+
/**
* Write PER selection for OPTIONAL fields.
* @param s stream
stream_write_uint8(s, selection);
}
+boolean per_read_number_of_sets(STREAM* s, uint8* number)
+{
+ stream_read_uint8(s, *number);
+ return True;
+}
+
/**
* Write PER number of sets for SET OF.
* @param s stream
stream_write_uint8(s, 0);
}
+boolean per_read_integer(STREAM* s, uint32* integer)
+{
+ int length;
+
+ per_read_length(s, &length);
+
+ if (length == 1)
+ stream_read_uint8(s, *integer);
+ else if (length == 2)
+ stream_read_uint16_be(s, *integer);
+ else
+ return False;
+
+ return True;
+}
+
+boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min)
+{
+ stream_read_uint16_be(s, *integer);
+
+ if (*integer + min > 0xFFFF)
+ return False;
+
+ *integer += min;
+
+ return True;
+}
+
+boolean per_read_enumerated(STREAM* s, uint8* enumerated)
+{
+ stream_read_uint8(s, *enumerated);
+ return True;
+}
+
+boolean per_read_object_identifier(STREAM* s, uint8 oid[6])
+{
+ uint8 t12;
+ int length;
+ uint8 a_oid[6];
+ boolean status;
+
+ per_read_length(s, &length); /* length */
+
+ if (length != 5)
+ return False;
+
+ stream_read_uint8(s, t12); /* first two tuples */
+ a_oid[0] = (t12 >> 4);
+ a_oid[1] = (t12 & 0x0F);
+
+ stream_read_uint8(s, a_oid[2]); /* tuple 3 */
+ stream_read_uint8(s, a_oid[3]); /* tuple 4 */
+ stream_read_uint8(s, a_oid[4]); /* tuple 5 */
+ stream_read_uint8(s, a_oid[5]); /* tuple 6 */
+
+ if ((a_oid[0] == oid[0]) && (a_oid[1] == oid[1]) &&
+ (a_oid[2] == oid[2]) && (a_oid[3] == oid[3]) &&
+ (a_oid[4] == oid[4]) && (a_oid[5] == oid[5]))
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+}
+
/**
* Write PER OBJECT_IDENTIFIER (OID)
* @param s stream
stream_write_uint8(s, str[i]);
}
+boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min)
+{
+ int i;
+ int mlength;
+ uint8* a_oct_str;
+
+ per_read_length(s, &mlength);
+
+ if (mlength + min != length)
+ return False;
+
+ a_oct_str = s->p;
+ stream_seek(s, length);
+
+ for (i = 0; i < length; i++)
+ {
+ if (a_oct_str[i] != oct_str[i])
+ return False;
+ }
+
+ return True;
+}
+
/**
* Write PER OCTET_STRING
* @param s stream
#include <freerdp/utils/stream.h>
+boolean per_read_length(STREAM* s, int* length);
void per_write_length(STREAM* s, int length);
+boolean per_read_choice(STREAM* s, uint8* choice);
void per_write_choice(STREAM* s, uint8 choice);
+boolean per_read_selection(STREAM* s, uint8* selection);
void per_write_selection(STREAM* s, uint8 selection);
+boolean per_read_number_of_sets(STREAM* s, uint8* number);
void per_write_number_of_sets(STREAM* s, uint8 number);
void per_write_padding(STREAM* s, int length);
+boolean per_read_integer(STREAM* s, uint32* integer);
+boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min);
+boolean per_read_enumerated(STREAM* s, uint8* enumerated);
void per_write_object_identifier(STREAM* s, uint8 oid[6]);
+boolean per_read_object_identifier(STREAM* s, uint8 oid[6]);
+boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min);
void per_write_octet_string(STREAM* s, uint8* oct_str, int length, int min);
void per_write_numeric_string(STREAM* s, uint8* num_str, int length, int min);