libfreerdp-core: parsing of GCC Conference Create Response
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Sat, 9 Jul 2011 21:28:30 +0000 (17:28 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Sat, 9 Jul 2011 21:28:30 +0000 (17:28 -0400)
cunit/test_gcc.c
cunit/test_gcc.h
libfreerdp-core/gcc.c
libfreerdp-core/gcc.h
libfreerdp-core/mcs.c
libfreerdp-core/per.c
libfreerdp-core/per.h

index 85cecac..d05389e 100644 (file)
@@ -39,7 +39,7 @@ int add_gcc_suite(void)
 {
        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);
@@ -68,7 +68,7 @@ uint8 gcc_user_data[284] =
        "\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"
@@ -90,7 +90,7 @@ uint8 gcc_create_conference_request_expected[307] =
        "\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;
@@ -99,10 +99,10 @@ void test_gcc_write_create_conference_request(void)
        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] =
index a672f86..2ddce03 100644 (file)
@@ -23,7 +23,7 @@ int init_gcc_suite(void);
 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);
index 038dfa1..c4a6de8 100644 (file)
  *     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}
@@ -105,7 +130,7 @@ uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
  * @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 */
@@ -127,12 +152,56 @@ void gcc_write_create_conference_request(STREAM* s, STREAM* user_data)
        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}
index 5f38b87..8a0cbe6 100644 (file)
@@ -99,7 +99,8 @@
 /* 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);
index afab69e..93a57c8 100644 (file)
@@ -250,7 +250,7 @@ void mcs_send_connect_initial(rdpMcs* mcs)
        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);
@@ -293,7 +293,7 @@ void mcs_recv_connect_response(rdpMcs* mcs)
 
        ber_read_octet_string(s, &length);
 
-       printf("userData, length:%d\n", length);
+       gcc_read_conference_create_response(s);
 }
 
 /**
index 58930d1..058cf88 100644 (file)
 
 #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
@@ -33,6 +53,12 @@ void per_write_length(STREAM* s, int length)
                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
@@ -44,6 +70,12 @@ void per_write_choice(STREAM* s, uint8 choice)
        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
@@ -55,6 +87,12 @@ void per_write_selection(STREAM* s, uint8 selection)
        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
@@ -80,6 +118,73 @@ void per_write_padding(STREAM* s, int length)
                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
@@ -112,6 +217,29 @@ void per_write_string(STREAM* s, uint8* str, int length)
                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
index 456e6a0..8c9cb50 100644 (file)
 
 #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);