libfreerdp-core: encoding of GCC create conference request + unit tests
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 4 Jul 2011 23:13:01 +0000 (19:13 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 4 Jul 2011 23:13:01 +0000 (19:13 -0400)
cunit/CMakeLists.txt
cunit/test_freerdp.c
cunit/test_gcc.c [new file with mode: 0644]
cunit/test_gcc.h [new file with mode: 0644]
libfreerdp-core/gcc.c
libfreerdp-core/gcc.h
libfreerdp-core/per.c
libfreerdp-core/per.h

index 769199c..ef3f0e2 100644 (file)
@@ -27,6 +27,8 @@ add_executable(test_freerdp
        test_per.h
        test_ber.c
        test_ber.h
+       test_gcc.c
+       test_gcc.h
        test_color.c
        test_color.h
        test_libgdi.c
index 0e22a01..cf974ae 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "test_per.h"
 #include "test_ber.h"
+#include "test_gcc.h"
 #include "test_color.h"
 #include "test_libgdi.h"
 #include "test_stream.h"
@@ -60,16 +61,23 @@ void assert_stream(STREAM* s, uint8* data, int length, const char* func, int lin
        int actual_length;
        uint8* actual_data;
 
+       actual_data = s->buffer;
        actual_length = stream_get_length(s);
 
        if (actual_length != length)
        {
-               printf("\n %s (%d): length mismatch, actual:%d, expected:%d", func, line, actual_length, length);
+               printf("\n %s (%d): length mismatch, actual:%d, expected:%d\n", func, line, actual_length, length);
+
+               printf("\nActual:\n");
+               freerdp_hexdump(actual_data, actual_length);
+
+               printf("Expected:\n");
+               freerdp_hexdump(data, length);
+
                CU_FAIL("assert_stream, length mismatch");
                return;
        }
 
-       actual_data = s->buffer;
        for (i = 0; i < length; i++)
        {
                if (actual_data[i] != data[i])
@@ -133,6 +141,10 @@ int main(int argc, char* argv[])
                        {
                                add_ber_suite();
                        }
+                       else if (strcmp("gcc", argv[*pindex]) == 0)
+                       {
+                               add_gcc_suite();
+                       }
 
                        *pindex = *pindex + 1;
                }
diff --git a/cunit/test_gcc.c b/cunit/test_gcc.c
new file mode 100644 (file)
index 0000000..5d2cad0
--- /dev/null
@@ -0,0 +1,102 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * T.124 Generic Conference Control (GCC) Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gcc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/utils/hexdump.h>
+#include <freerdp/utils/stream.h>
+
+#include "test_gcc.h"
+
+int init_gcc_suite(void)
+{
+       return 0;
+}
+
+int clean_gcc_suite(void)
+{
+       return 0;
+}
+
+int add_gcc_suite(void)
+{
+       add_test_suite(gcc);
+
+       add_test_function(gcc_write_create_conference_request);
+
+       return 0;
+}
+
+uint8 gcc_user_data[284] =
+       "\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\x00\x4c\x00\x54\x00\x4f\x00"
+       "\x4e\x00\x53\x00\x2d\x00\x44\x00\x45\x00\x56\x00\x32\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00"
+       "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x01\xCA\x01\x00\x00\x00\x00\x00\x18\x00\x07\x00"
+       "\x01\x00\x36\x00\x39\x00\x37\x00\x31\x00\x32\x00\x2d\x00\x37\x00"
+       "\x38\x00\x33\x00\x2d\x00\x30\x00\x33\x00\x35\x00\x37\x00\x39\x00"
+       "\x37\x00\x34\x00\x2d\x00\x34\x00\x32\x00\x37\x00\x31\x00\x34\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x04\xC0\x0C\x00\x0D\x00\x00\x00"
+       "\x00\x00\x00\x00\x02\xC0\x0C\x00\x1B\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\xC0\x2C\x00\x03\x00\x00\x00\x72\x64\x70\x64\x72\x00\x00\x00"
+       "\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] =
+       "\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"
+       "\x00\x4c\x00\x54\x00\x4f\x00\x4e\x00\x53\x00\x2d\x00\x44\x00\x45"
+       "\x00\x56\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"
+       "\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xCA\x01\x00\x00"
+       "\x00\x00\x00\x18\x00\x07\x00\x01\x00\x36\x00\x39\x00\x37\x00\x31"
+       "\x00\x32\x00\x2d\x00\x37\x00\x38\x00\x33\x00\x2d\x00\x30\x00\x33"
+       "\x00\x35\x00\x37\x00\x39\x00\x37\x00\x34\x00\x2d\x00\x34\x00\x32"
+       "\x00\x37\x00\x31\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"
+       "\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00\x00\x02\xC0\x0C\x00\x1B"
+       "\x00\x00\x00\x00\x00\x00\x00\x03\xC0\x2C\x00\x03\x00\x00\x00\x72"
+       "\x64\x70\x64\x72\x00\x00\x00\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";
+
+void test_gcc_write_create_conference_request(void)
+{
+       STREAM* s;
+       STREAM user_data;
+
+       user_data.buffer = gcc_user_data;
+       user_data.capacity = sizeof(gcc_user_data);
+       user_data.ptr = user_data.buffer + user_data.capacity;
+
+       s = stream_new(sizeof(gcc_create_conference_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));
+}
diff --git a/cunit/test_gcc.h b/cunit/test_gcc.h
new file mode 100644 (file)
index 0000000..ab3e240
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * T.124 Generic Conference Control (GCC) Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_freerdp.h"
+
+int init_gcc_suite(void);
+int clean_gcc_suite(void);
+int add_gcc_suite(void);
+
+void test_gcc_write_create_conference_request(void);
index 3a117bc..1e59f5d 100644 (file)
  *     connectPDU      OCTET_STRING
  * }
  *
+ * Key ::= CHOICE
+ * {
+ *     object                          OBJECT_IDENTIFIER,
+ *     h221NonStandard                 H221NonStandardIdentifier
+ * }
+ *
  * ConnectGCCPDU ::= CHOICE
  * {
  *     conferenceCreateRequest         ConferenceCreateRequest,
  *     conferenceInviteResponse        ConferenceInviteResponse,
  *     ...
  * }
+ *
+ * ConferenceCreateRequest ::= SEQUENCE
+ * {
+ *     conferenceName                  ConferenceName,
+ *     convenerPassword                Password OPTIONAL,
+ *     password                        Password OPTIONAL,
+ *     lockedConference                BOOLEAN,
+ *     listedConference                BOOLEAN,
+ *     conductibleConference           BOOLEAN,
+ *     terminationMethod               TerminationMethod,
+ *     conductorPrivileges             SET OF Privilege OPTIONAL,
+ *     conductedPrivileges             SET OF Privilege OPTIONAL,
+ *     nonConductedPrivileges          SET OF Privilege OPTIONAL,
+ *     conferenceDescription           TextString OPTIONAL,
+ *     callerIdentifier                TextString OPTIONAL,
+ *     userData                        UserData OPTIONAL,
+ *     ...,
+ *     conferencePriority              ConferencePriority OPTIONAL,
+ *     conferenceMode                  ConferenceMode OPTIONAL
+ * }
+ *
+ * ConferenceName ::= SEQUENCE
+ * {
+ *     numeric                         SimpleNumericString
+ *     text                            SimpleTextString OPTIONAL,
+ *     ...
+ * }
+ *
+ * SimpleNumericString ::= NumericString (SIZE (1..255)) (FROM ("0123456789"))
+ *
+ * UserData ::= SET OF SEQUENCE
+ * {
+ *     key                             Key,
+ *     value                           OCTET_STRING OPTIONAL
+ * }
+ *
+ * H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255))
+ *
  */
 
 /* http://msdn.microsoft.com/en-us/library/cc240836/ */
 
-uint8 t124_oid[6] = { 0, 0, 20, 124, 0, 1 };
+/*
+ * OID = 0.0.20.124.0.1
+ * { itu-t(0) recommendation(0) t(20) t124(124) version(0) 1 }
+ * v.1 of ITU-T Recommendation T.124 (Feb 1998): "Generic Conference Control"
+ */
+uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
+
+void
+gcc_write_create_conference_request(STREAM* s, STREAM* user_data)
+{
+       /* ConnectData */
+       per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */
+       per_write_object_identifier(s, t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */
+
+       /* ConnectData::connectPDU (OCTET_STRING) */
+       per_write_length(s, stream_get_length(user_data) + 14); /* connectPDU length */
+
+       /* ConnectGCCPDU */
+       per_write_choice(s, 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */
+       per_write_selection(s, 0x08); /* select optional userData from ConferenceCreateRequest */
+
+       /* ConferenceCreateRequest::conferenceName */
+       per_write_numeric_string(s, "1", 1, 1); /* ConferenceName::numeric */
+       per_write_padding(s, 1); /* padding */
+
+       /* UserData (SET OF SEQUENCE) */
+       per_write_number_of_sets(s, 1); /* one set of UserData */
+       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" */
 
+       /* userData::value (OCTET_STRING) */
+       per_write_octet_string(s, user_data->buffer, stream_get_length(user_data), 0); /* array of client data blocks */
+}
index 69714b9..a099ce9 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <freerdp/utils/stream.h>
 
-
+void
+gcc_write_create_conference_request(STREAM* s, STREAM* user_data);
 
 #endif /* __GCC_H */
index 8228ab1..dc624b2 100644 (file)
@@ -29,6 +29,33 @@ per_write_length(STREAM* s, int length)
 }
 
 void
+per_write_choice(STREAM* s, uint8 choice)
+{
+       stream_write_uint8(s, choice);
+}
+
+void
+per_write_selection(STREAM* s, uint8 selection)
+{
+       stream_write_uint8(s, selection);
+}
+
+void
+per_write_number_of_sets(STREAM* s, uint8 number)
+{
+       stream_write_uint8(s, number);
+}
+
+void
+per_write_padding(STREAM* s, int length)
+{
+       int i;
+
+       for (i = 0; i < length; i++)
+               stream_write_uint8(s, 0);
+}
+
+void
 per_write_object_identifier(STREAM* s, uint8 oid[6])
 {
        uint8 t12 = (oid[0] << 4) & (oid[1] & 0x0F);
@@ -39,3 +66,50 @@ per_write_object_identifier(STREAM* s, uint8 oid[6])
        stream_write_uint8(s, oid[4]); /* tuple 5 */
        stream_write_uint8(s, oid[5]); /* tuple 6 */
 }
+
+void
+per_write_string(STREAM* s, uint8* str, int length)
+{
+       int i;
+
+       for (i = 0; i < length; i++)
+               stream_write_uint8(s, str[i]);
+}
+
+void
+per_write_octet_string(STREAM* s, uint8* oct_str, int length, int min)
+{
+       int i;
+       int mlength;
+
+       mlength = (length - min >= 0) ? length - min : min;
+
+       per_write_length(s, mlength);
+
+       for (i = 0; i < length; i++)
+               stream_write_uint8(s, oct_str[i]);
+}
+
+void
+per_write_numeric_string(STREAM* s, uint8* num_str, int length, int min)
+{
+       int i;
+       int mlength;
+       uint8 num, c1, c2;
+
+       mlength = (length - min >= 0) ? length - min : min;
+
+       per_write_length(s, mlength);
+
+       for (i = 0; i < length; i += 2)
+       {
+               c1 = num_str[i];
+               c2 = ((i + 1) < length) ? num_str[i + 1] : 0x30;
+
+               c1 = (c1 - 0x30) % 10;
+               c2 = (c2 - 0x30) % 10;
+               num = (c1 << 4) | c2;
+
+               stream_write_uint8(s, num); /* string */
+       }
+}
index cbb8261..692f91d 100644 (file)
 void
 per_write_length(STREAM* s, int length);
 void
+per_write_choice(STREAM* s, uint8 choice);
+void
+per_write_selection(STREAM* s, uint8 selection);
+void
+per_write_number_of_sets(STREAM* s, uint8 number);
+void
+per_write_padding(STREAM* s, int length);
+void
 per_write_object_identifier(STREAM* s, uint8 oid[6]);
+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);
 
 #endif /* __PER_H */