1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 // ---------------------------------------------------------------------- 19 // 20 // This Software is an original work of authorship of PacketVideo Corporation. 21 // Portions of the Software were developed in collaboration with NTT DoCoMo, 22 // Inc. or were derived from the public domain or materials licensed from 23 // third parties. Title and ownership, including all intellectual property 24 // rights in and to the Software shall remain with PacketVideo Corporation 25 // and NTT DoCoMo, Inc. 26 // 27 // ----------------------------------------------------------------------- 28 // ============================================================ 29 // FILE: GenericPER.c 30 // 31 // DESCRIPTION: Generic PER encode/decode routines. These are 32 // called by the automatically generated MiniParser code. 33 // 34 // Written by Ralph Neff, PacketVideo, 2/8/2000 35 // (c) 2000 PacketVideo Corp. 36 // ============================================================ 37 38 #include "per_headers.h" 39 #include "analyzeper.h" 40 #include "genericper.h" 41 #include "oscl_error_codes.h" 42 #include "oscl_mem.h" 43 #include "oscl_stdstring.h" 44 #include "pvlogger.h" 45 46 #define STREAM_ADDITION 64 /* Output stream grows in increments */ 47 /* of this many bytes. */ 48 49 const uint8 MaskBit[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; 50 51 /***********************************************************/ 52 /*=========================================================*/ 53 /*============ DECODING ROUTINES (Generic PER) ============*/ 54 /*=========================================================*/ 55 /***********************************************************/ 56 57 /* --------------------------------------------- */ 58 /* ------------- LOW LEVEL STREAM -------------- */ 59 /* --------------------------------------------- */ 60 61 // ========================================================= 62 // ErrorMessage() 63 // 64 // This function is a generic error call for PER routines. 65 // 66 // NOTE: Removed the MessageBox called and replaced with a 67 // call to the analyzer via Show245(). Since tag informaion 68 // isn't easy to get (encoder/decoder autogen routines don't 69 // provide tags, and deleter autogen routines don't even have 70 // a tag defined!), we will fix to the "PER Decoder" tag for 71 // now. The proper thing to do would be to use a newly 72 // defined "PER Error" tag. But it's not so important to 73 // do this, since the source of the error is always defined 74 // in the message itself. (RAN-MessageBox) 10/5/01 75 // ========================================================= 76 void ErrorMessage(const char *msg) 77 { 78 OSCL_UNUSED_ARG(msg); 79 80 PVLogger *logger = PVLogger::GetLoggerObject("3g324m.h245.per"); 81 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, logger, PVLOGMSG_ERR, (0, "GenericPer::ErrorMessage - %s", msg)); 82 } 83 84 void ErrorMessageAndLeave(const char *msg) 85 { 86 ErrorMessage(msg); 87 PVLogger *logger = PVLogger::GetLoggerObject("3g324m.h245.per"); 88 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, logger, PVLOGMSG_ERR, (0, "GenericPer::ErrorMessageAndLeave - LEAVE")); 89 OSCL_LEAVE(OsclErrCorrupt); 90 } 91 92 // ========================================================= 93 // ReadBits() 94 // 95 // This function reads some number of bits from the 96 // input stream. 97 // ========================================================= 98 uint8 ReadBits(uint32 number, PS_InStream stream) 99 { 100 uint8 x; 101 uint8 NextBit, BitSize; 102 103 if (number > 8) 104 { 105 ErrorMessageAndLeave("ReadBits(): Max number (8) exceeded"); 106 } 107 108 BitSize = (uint8)(stream->bitIndex + number); 109 x = (uint8)(stream->data[0] & MaskBit[(int)stream->bitIndex ]); 110 if (BitSize > 8) 111 { 112 NextBit = (uint8)(BitSize - 8); 113 x <<= NextBit; 114 ++stream->data; 115 x |= ((stream->data[0]) & ~MaskBit[(int)stream->bitIndex ]) >> (8 - NextBit); 116 } 117 else if (BitSize < 8) 118 { 119 NextBit = BitSize; 120 x >>= (8 - NextBit); 121 } 122 else 123 { 124 NextBit = 0; 125 ++stream->data; 126 } 127 128 stream->bitIndex = NextBit; 129 return(x); 130 } 131 132 // ========================================================= 133 // ReadRemainingBits() 134 // 135 // This function advances to the next octet boundary in 136 // the input stream. If the stream already points to 137 // an octet boundary, no action is taken. 138 // ========================================================= 139 void ReadRemainingBits(PS_InStream stream) 140 { 141 if (stream->bitIndex) 142 { 143 stream->bitIndex = 0; 144 ++stream->data; 145 } 146 } 147 148 // ========================================================= 149 // ReadOctets() 150 // 151 // This function reads one or more octets from the input 152 // stream. Input arguments are: 153 // uint32 number; /* Number of octets to read */ 154 // uint8* octets; /* Destination for octets */ 155 // uint8 reorder; /* Reorder for little-endian machine? */ 156 // PS_InStream stream; /* Input stream */ 157 // ========================================================= 158 void ReadOctets(uint32 number, uint8* octets, uint8 reorder, PS_InStream stream) 159 { 160 ReadRemainingBits(stream); /* Octet alignment */ 161 162 if (number == 0) /* No action */ 163 { 164 return; 165 } 166 else if (number <= 4 && reorder) /* Apply reordering */ 167 { 168 switch (number) 169 { 170 case 1: 171 octets[0] = stream->data[0]; 172 break; 173 case 2: 174 octets[0] = stream->data[1]; 175 octets[1] = stream->data[0]; 176 break; 177 case 3: 178 octets[0] = stream->data[2]; 179 octets[1] = stream->data[1]; 180 octets[2] = stream->data[0]; 181 break; 182 case 4: 183 octets[0] = stream->data[3]; 184 octets[1] = stream->data[2]; 185 octets[2] = stream->data[1]; 186 octets[3] = stream->data[0]; 187 break; 188 } 189 } 190 else 191 { 192 oscl_memcpy(octets, stream->data, number); /* Straight copy */ 193 } 194 195 stream->data += number; 196 } 197 198 199 /* --------------------------------------------- */ 200 /* ------------ HIGH LEVEL ASN DATA ------------ */ 201 /* --------------------------------------------- */ 202 203 204 // ========================================================= 205 // GetBoolean() 206 // 207 // This function reads a boolean from the input stream. 208 // ========================================================= 209 uint8 GetBoolean(PS_InStream stream) 210 { 211 return(ReadBits(1, stream)); 212 } 213 214 // ========================================================= 215 // GetInteger() X.691 Section 10.5 216 // 217 // This function decodes a constrained integer, given the 218 // lower/upper bounds. Note that bounds are uint32, which 219 // means min>=0, max<=4294967295. 220 // Assumes ALIGNED variant of PER. 221 // ========================================================= 222 uint32 GetInteger(uint32 lower, uint32 upper, PS_InStream stream) 223 { 224 uint32 value = 0, range; 225 uint8 nbits, nbytes = 0; 226 227 if (lower > upper) 228 { 229 ErrorMessageAndLeave("GetInteger(): Range is negative."); 230 return(lower); 231 } 232 range = upper - lower + 1; 233 234 if (range == 0) /* Special case: int32EGER(0..4294967295) */ 235 { 236 nbytes = (uint8)(ReadBits(2, stream) + 1); 237 ReadOctets(nbytes, (uint8*)&value, 1, stream); 238 return(value); 239 } 240 else if (range == 1) /* 0-bits */ 241 return(lower); 242 else if (range < 256) /* Bit-field cases */ 243 { 244 if (range <= 2) nbits = 1; 245 else if (range <= 4) nbits = 2; 246 else if (range <= 8) nbits = 3; 247 else if (range <= 16) nbits = 4; 248 else if (range <= 32) nbits = 5; 249 else if (range <= 64) nbits = 6; 250 else if (range <= 128) nbits = 7; 251 else nbits = 8; 252 value = ReadBits(nbits, stream); 253 if (lower + value > upper) 254 { 255 ErrorMessageAndLeave("GetInteger(): Integer exceeds range"); 256 } 257 return(lower + value); 258 } 259 else /* One or more octets */ 260 { 261 if (range == 256) nbytes = 1; 262 else if (range <= 65536) nbytes = 2; 263 else nbytes = (uint8)(ReadBits(2, stream) + 1); 264 ReadOctets(nbytes, (uint8*)&value, 1, stream); 265 if (lower + value > upper) 266 { 267 ErrorMessageAndLeave("GetInteger(): exceeds range"); 268 } 269 return(lower + value); 270 } 271 } 272 273 // ========================================================= 274 // GetSignedInteger() X.691 Section 10.5 275 // 276 // This function decodes a constrained integer, given the 277 // lower/upper bounds. The only difference from GetInteger() 278 // is that the bounds and returned values are int32, and 279 // so may be negative. 280 // Assumes ALIGNED variant of PER. 281 // ========================================================= 282 int32 GetSignedInteger(int32 lower, int32 upper, PS_InStream stream) 283 { 284 int32 value = 0, range; 285 uint8 nbits, nbytes = 0; 286 287 if (lower > upper) 288 { 289 ErrorMessageAndLeave("GetSignedInteger(): Range is negative."); 290 return(lower); 291 } 292 range = upper - lower + 1; 293 294 if (range == 0) 295 { 296 ErrorMessageAndLeave("GetSignedInteger(): Range is zero."); 297 return(lower); 298 } 299 else if (range == 1) /* 0-bits */ 300 return(lower); 301 else if (range < 256) /* Bit-field cases */ 302 { 303 if (range <= 2) nbits = 1; 304 else if (range <= 4) nbits = 2; 305 else if (range <= 8) nbits = 3; 306 else if (range <= 16) nbits = 4; 307 else if (range <= 32) nbits = 5; 308 else if (range <= 64) nbits = 6; 309 else if (range <= 128) nbits = 7; 310 else nbits = 8; 311 value = ReadBits(nbits, stream); 312 if (lower + value > upper) 313 { 314 ErrorMessageAndLeave("GetSignedInteger(): Integer exceeds range"); 315 } 316 return(lower + value); 317 } 318 else /* One or more octets */ 319 { 320 if (range == 256) nbytes = 1; 321 else if (range <= 65536) nbytes = 2; 322 else nbytes = (uint8)(ReadBits(2, stream) + 1); 323 ReadOctets(nbytes, (uint8*)&value, 1, stream); 324 if (lower + value > upper) 325 { 326 ErrorMessageAndLeave("GetSignedInteger(): GetInteger exceeds range"); 327 } 328 return(lower + value); 329 } 330 } 331 332 // ========================================================= 333 // GetUnboundedInteger() X.691 Section 12 334 // and also 10.4, 10.9. 335 // 336 // This function decodes an unbounded integer. The structure 337 // definition can only accomodate a uint32 return type, so if 338 // the decoded value is negative, we signal an error. 339 // Assumes ALIGNED variant of PER. 340 // ========================================================= 341 uint32 GetUnboundedInteger(PS_InStream stream) 342 { 343 uint32 nbytes, value = 0; 344 345 nbytes = GetLengthDet(stream); // Length Det (10.9) 346 ReadOctets(nbytes, (uint8*)&value, 1, stream); // Value (10.4) 347 348 // Check for negative value 349 if ((nbytes == 1 && value >= 0x7f) || 350 (nbytes == 2 && value >= 0x8000) || 351 (nbytes == 3 && value >= 0x800000) || 352 (nbytes == 4 && value >= 0x80000000)) 353 { 354 ErrorMessageAndLeave("GetUnboundedInteger: Found a negative value!"); 355 } 356 357 return(value); 358 } 359 360 // ========================================================= 361 // GetExtendedInteger() X.691 Section 12.1 362 // 363 // This function decodes a constrained integer with an 364 // extended range. We assume the value is unsigned, and 365 // that the ALIGNED variant of PER is used. 366 // ========================================================= 367 uint32 GetExtendedInteger(uint32 lower, uint32 upper, PS_InStream stream) 368 { 369 uint32 extension_bit, value; 370 371 extension_bit = ReadBits(1, stream); 372 if (extension_bit) 373 { 374 value = GetUnboundedInteger(stream); 375 } 376 else 377 { 378 value = GetInteger(lower, upper, stream); 379 } 380 381 return(value); 382 } 383 384 // ========================================================= 385 // GetOctetString() X.691 Section 16 386 // 387 // This function reads an OCTET STRING from the input stream. 388 // Bounds on the size, if any, are included in the input 389 // arguments. 390 // ========================================================= 391 void GetOctetString(uint8 unbounded, uint32 min, uint32 max, 392 PS_OCTETSTRING x, PS_InStream stream) 393 { 394 if (unbounded) /* ====Size is unbounded==== */ 395 { 396 x->size = (uint16) GetLengthDet(stream); 397 if (x->size) 398 { 399 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 400 ReadOctets(x->size, x->data, 0, stream); 401 } 402 else 403 { 404 x->data = NULL; 405 } 406 } 407 else /* ====Size is bounded==== */ 408 { 409 410 if (min > max) /* Error handling */ 411 { 412 ErrorMessageAndLeave("GetOctetString(): Constraint error (min>max)"); 413 } 414 415 if (min == max) /* Fixed size (no length det!) */ 416 { 417 x->size = (uint16) min; 418 if (x->size) 419 { 420 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 421 if (x->size > 2) 422 { 423 ReadOctets(x->size, x->data, 0, stream); 424 } 425 else if (x->size == 2) 426 { 427 x->data[0] = ReadBits(8, stream); 428 x->data[1] = ReadBits(8, stream); 429 } 430 else if (x->size == 1) 431 { 432 x->data[0] = ReadBits(8, stream); 433 } 434 } 435 else 436 { 437 x->data = NULL; 438 } 439 } 440 else /* Constrained size */ 441 { 442 x->size = (uint16) GetInteger(min, max, stream); 443 if (x->size) 444 { 445 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 446 ReadOctets(x->size, x->data, 0, stream); 447 } 448 else 449 { 450 x->data = NULL; 451 } 452 } 453 } 454 } 455 456 // ========================================================= 457 // GetBitString() X.691 Section 16 458 // 459 // This function reads a BIT STRING from the input stream. 460 // Bounds on the size, if any, are included in the input 461 // arguments. The BITSTRING structure (x) is returned. 462 // ========================================================= 463 void GetBitString(uint8 unbounded, uint32 min, uint32 max, 464 PS_BITSTRING x, PS_InStream stream) 465 { 466 uint32 count; 467 uint8* temp; 468 469 if (unbounded) /* ====Size is unbounded==== */ 470 { 471 count = GetLengthDet(stream); 472 x->size = (uint16) count; 473 temp = x->data = (uint8*) OSCL_DEFAULT_MALLOC((1 + x->size / 8) * sizeof(uint8)); 474 while (count >= 8) 475 { 476 temp[0] = ReadBits(8, stream); 477 ++temp; 478 count -= 8; 479 } 480 temp[0] = (uint8)(ReadBits(count, stream) << (8 - count)); 481 } 482 else /* ====Size is bounded==== */ 483 { 484 485 if (min > max) /* Error handling */ 486 { 487 ErrorMessageAndLeave("GetBitString(): Constraint error (min>max)"); 488 } 489 490 if (min == max) /* Fixed size (no length det!) */ 491 { 492 count = min; 493 x->size = (uint16) count; 494 temp = x->data = (uint8*) OSCL_DEFAULT_MALLOC((1 + x->size / 8) * sizeof(uint8)); 495 if (x->size > 16) 496 { 497 ReadRemainingBits(stream); /* Octet align */ 498 } 499 while (count >= 8) 500 { 501 temp[0] = ReadBits(8, stream); 502 ++temp; 503 count -= 8; 504 } 505 temp[0] = (uint8)(ReadBits(count, stream) << (8 - count)); 506 } 507 else /* Constrained size */ 508 { 509 count = GetInteger(min, max, stream); 510 x->size = (uint16) count; 511 temp = x->data = (uint8*) OSCL_DEFAULT_MALLOC((1 + x->size / 8) * sizeof(uint8)); 512 ReadRemainingBits(stream); 513 while (count >= 8) 514 { 515 temp[0] = ReadBits(8, stream); 516 ++temp; 517 count -= 8; 518 } 519 } 520 } 521 } 522 523 // ========================================================= 524 // GetCharString() (RAN-UII) 525 // 526 // This function decodes a character string from a stream. 527 // Currently it only handles the special case of DTMF user 528 // input (that is, signalType in UserInputIndication). 529 // However, it should be straightforward to extend this 530 // to handle generic restrictions on the four common 531 // types (IA5String, NumericString, PrintableString, 532 // and VisibleString). See X.691 Clause 26.5 for details. 533 // NOTE: For now I'm adding NULL string termination so that 534 // the analyzer (ShowPERCharString() ) will correctly display 535 // it on the decode side. Should correct this at some point, 536 // since x->data should really only contain characters that 537 // were pulled from the input stream. 538 // ========================================================= 539 void GetCharString(const char *stringName, 540 uint8 unbounded, uint32 min, uint32 max, const char *from, 541 PS_int8STRING x, PS_InStream stream) 542 { 543 if (oscl_strncmp(stringName, "IA5String", oscl_strlen("IA5String")) == 0 && // Validate DTMF UII case 544 unbounded == 0 && 545 min == 1 && 546 max == 1 && 547 oscl_strncmp(from, "0123456789#*ABCD!", oscl_strlen("0123456789#*ABCD!")) == 0) 548 { 549 x->size = 2; 550 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 551 x->data[0] = ReadBits(8, stream); // Read single character, 552 // Normal ascii value, not octet aligned 553 x->data[1] = 0; // NULL terminate 554 } 555 else if (oscl_strncmp(stringName, "GeneralString", oscl_strlen("GeneralString")) == 0) // Validate GeneralString case (RAN-ALPHA) 556 { 557 x->size = (uint16)(1 + GetLengthDet(stream)); // (leave extra space for NULL) 558 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 559 ReadOctets(x->size - 1, x->data, 1, stream); 560 x->data[x->size-1] = 0; // NULL terminate 561 } 562 else 563 { 564 x->size = 0; 565 x->data = NULL; 566 ErrorMessageAndLeave("GetCharString(): Not yet implemented."); 567 } 568 } 569 570 // ========================================================= 571 // GetObjectID() X.691 Section 23 572 // 573 // This function reads an OBJECT IDENTIFIER from the input 574 // stream. This is just a length determinant, followed by 575 // a variable number of octets. 576 // ========================================================= 577 void GetObjectID(PS_OBJECTIDENT x, PS_InStream stream) 578 { 579 x->size = (uint16) GetLengthDet(stream); 580 if (x->size) 581 { 582 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 583 ReadOctets(x->size, x->data, 0, stream); 584 } 585 else 586 { 587 x->data = NULL; 588 } 589 } 590 591 592 /* --------------------------------------------- */ 593 /* --------------- OTHER CALLS ------------------*/ 594 /* --------------------------------------------- */ 595 596 // ========================================================= 597 // GetLengthDet() X.691 Section 10.9 598 // 599 // Decodes a general length determinant from the input 600 // stream. Assumes ALIGNED variant of PER. 601 // ========================================================= 602 uint32 GetLengthDet(PS_InStream stream) 603 { 604 uint32 length; 605 uint8 byte1, byte2; 606 uint8 mask1 = 0x80; /* 10000000 */ 607 uint8 mask2 = 0x40; /* 01000000 */ 608 uint8 mask3 = 0x3f; /* 00111111 */ 609 610 ReadOctets(1, (uint8*)&byte1, 0, stream); /* Get first byte */ 611 if (!(byte1&mask1)) /* 0xxxxxxx ==>Single octet case */ 612 { 613 length = (uint32) byte1; 614 } 615 else if (!(byte1&mask2)) /* 10xxxxxx ==>Dual octet case */ 616 { 617 ReadOctets(1, (uint8*)&byte2, 0, stream); /* Second byte */ 618 length = (((uint32)(byte1 & mask3)) << 8) + (int32)byte2; 619 } 620 else 621 { 622 ErrorMessageAndLeave("GetLengthDet(): Fragmented Length Dets Not Supported."); 623 return(0); 624 } 625 return(length); 626 } 627 628 // ========================================================= 629 // GetNormSmallLength() X.691 Section 10.9.3.4 630 // 631 // Decodes a Normally Small length determinant from the 632 // input stream. (In SEQUENCE, this gets the size of an 633 // unknown extensions map). 634 // Assumes ALIGNED variant of PER. 635 // ========================================================= 636 uint32 GetNormSmallLength(PS_InStream stream) 637 { 638 uint8 value = 0; 639 uint8 mask = 0x40; /* 01000000 */ 640 641 value = ReadBits(7, stream); 642 if (value&mask) 643 { 644 ErrorMessageAndLeave("GetNormSmallLength(): Range exceeded."); 645 return(0); 646 } 647 return((uint32)value + 1); /* Valid range is 1...64 */ 648 } 649 650 // ========================================================= 651 // GetNormSmallValue() X.691 Section 10.6 652 // 653 // Decodes a Normally Small Nonnegative Whole Number from 654 // the input stream. 655 // (In CHOICE, gets choice index when extension is ON.) 656 // Assumes ALIGNED variant of PER. 657 // ========================================================= 658 uint32 GetNormSmallValue(PS_InStream stream) 659 { 660 uint8 value = 0; 661 uint8 mask = 0x40; /* 01000000 */ 662 663 value = ReadBits(7, stream); 664 if (value&mask) 665 { 666 ErrorMessageAndLeave("GetNormSmallValue(): range exceeded."); 667 return(0); 668 } 669 return((uint32)value); /* Valid range is 0...63 */ 670 } 671 672 // ========================================================= 673 // SkipOneExtension() X.691 Section 18.9 674 // 675 // The general length is first read, and that number of 676 // octets are then skipped. 677 // (In SEQUENCE, this skips over a single unknown extension. 678 // In CHOICE, this skips an item that has been chosen from 679 // the extension, assuming the choice index has already 680 // been read). 681 // Assumes aligned variant of PER. 682 // ========================================================= 683 void SkipOneExtension(PS_InStream stream) 684 { 685 uint16 length; 686 uint8 buffer[32]; 687 688 length = (uint16) GetLengthDet(stream); 689 while (length > 32) /* Pieces of at most 32 bytes */ 690 { 691 ReadOctets(32, buffer, 0, stream); 692 length -= 32; 693 } 694 ReadOctets(length, buffer, 0, stream); /* Leftovers */ 695 } 696 697 // ========================================================= 698 // SkipAllExtensions() X.691 Section 18.9 699 // 700 // For SEQUENCE, this skips over all unknown extensions. 701 // This includes reading the SigMap, including size. 702 // Call this routine at the location of the ext marker [...]. 703 // 704 // NOTE: This routine may be obsolete. Miniparser code 705 // instead uses a combination of GetUnknownSigMap() and 706 // SkipUnreadExtensions(). 707 // ========================================================= 708 void SkipAllExtensions(PS_InStream stream) 709 { 710 uint32 size, i, num_to_skip = 0; 711 712 size = GetNormSmallLength(stream); /* Length of SigMap */ 713 /* Read sigmap, counting number of significant extensions */ 714 for (i = 0; i < size; ++i) 715 { 716 num_to_skip += ReadBits(1, stream); 717 } 718 for (i = 0; i < num_to_skip; ++i) 719 { 720 SkipOneExtension(stream); 721 } 722 } 723 724 // ========================================================= 725 // GetChoiceIndex() X.691 Sections 22.4 - 22.8 726 // 727 // Reads the extension bit and choice index from the input 728 // stream, and constructs a (possibly extended) choice index. 729 // Assumes ALIGNED variant of PER. 730 // --------------------------------------------------------- 731 // Inputs: rootnum (number of objects in root) 732 // extmarker (0 if no extension marker, 1 otherwise) 733 // ========================================================= 734 uint16 GetChoiceIndex(uint32 rootnum, uint8 extmarker, PS_InStream stream) 735 { 736 uint8 extension; 737 uint16 index; 738 739 extension = 0; 740 if (extmarker) /* Get extension bit */ 741 { 742 extension = ReadBits(1, stream); 743 } 744 745 if (!extension) /* ---Item in root--- */ 746 { 747 if (rootnum == 1) /* Trivial index */ 748 { 749 return(0); 750 } 751 else /* Standard index */ 752 { 753 index = (uint16) GetInteger(0, rootnum - 1, stream); 754 } /* ---Item in extension--- */ 755 } 756 else /* Extended index */ 757 { 758 index = (uint16)(GetNormSmallValue(stream) + rootnum); 759 } 760 761 return(index); 762 } 763 764 // ========================================================= 765 // GetUnknownSigMap() X.691 Sections 18.7 - 18.8 766 // 767 // This function reads an unknown significance map from 768 // the input stream. This includes the length of the 769 // significance map, and an options bit corresponding to 770 // each of the possible extension items. The completed 771 // map is returned in a special structure. 772 // ========================================================= 773 PS_UnknownSigMap GetUnknownSigMap(PS_InStream stream) 774 { 775 int32 i; 776 PS_UnknownSigMap x; 777 778 x = (PS_UnknownSigMap) OSCL_DEFAULT_MALLOC(sizeof(S_UnknownSigMap)); 779 780 x->size = (uint16) GetNormSmallLength(stream); 781 x->optionFlags = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8)); 782 for (i = 0; i < x->size; ++i) 783 { 784 x->optionFlags[i] = ReadBits(1, stream); 785 } 786 x->extensionsRead = 0; 787 788 return(x); 789 } 790 791 // ========================================================= 792 // SigMapValue() 793 // 794 // This function reads a single options flag from an 795 // unknown significance map (UnknownSigMap). If the 796 // index of the desired value exceeds the size of the 797 // map, the return value is zero. 798 // ========================================================= 799 uint8 SigMapValue(uint32 index, PS_UnknownSigMap map) 800 { 801 if (index < map->size) 802 { 803 return(map->optionFlags[index]); 804 } 805 else 806 { 807 return(0); 808 } 809 } 810 811 // ========================================================= 812 // ExtensionPrep() 813 // 814 // This function is called immediately before reading each 815 // unknown extension item in a SEQUENCE. It performs two 816 // actions: 817 // 1. Records within the unknown sigmap that another 818 // extension is being read (++map->extensionsRead). 819 // This is so SkipUnreadExtensions() later knows 820 // how many extensions should be skipped. 821 // 2. Reads and discards the length wrapper from the 822 // input stream. 823 // ========================================================= 824 void ExtensionPrep(PS_UnknownSigMap map, PS_InStream stream) 825 { 826 ++map->extensionsRead; 827 GetLengthDet(stream); 828 } 829 830 // ========================================================= 831 // SkipUnreadExtensions() 832 // 833 // This function skips any unread (and possibly unknown) items 834 // in the extension of a SEQUENCE. In order for this to work, 835 // previously read extension items must have been counted in 836 // map->extensionsRead; see ExtensionPrep() for details. 837 // 838 // This routine takes the following actions: 839 // 1. Uses map->extensionsRead to determine how many 840 // extension items remain in the input stream. 841 // 2. Skips remaining extension items. 842 // 3. Frees the UnknownSigMap. 843 // 4. Returns the number of extensions skipped. 844 // ========================================================= 845 uint32 SkipUnreadExtensions(PS_UnknownSigMap map, PS_InStream stream) 846 { 847 uint32 i, numExtensions; 848 849 /* Compute the number of extensions to skip */ 850 numExtensions = 0; 851 for (i = 0; i < map->size; ++i) 852 { 853 numExtensions += map->optionFlags[i]; 854 } 855 numExtensions -= map->extensionsRead; 856 857 /* Skip remaining extensions */ 858 for (i = 0; i < numExtensions; ++i) 859 { 860 SkipOneExtension(stream); 861 } 862 863 /* Free map, return number skipped */ 864 OSCL_DEFAULT_FREE(map->optionFlags); 865 OSCL_DEFAULT_FREE(map); 866 867 return(numExtensions); 868 } 869 870 // ========================================================= 871 // SkipOneOctet() 872 // 873 // Skip a single octet. This is used when a NULL is 874 // read from the extension of a CHOICE (since an empty 875 // octet is present) 876 // ========================================================= 877 void SkipOneOctet(PS_InStream stream) 878 { 879 uint8 temp; 880 881 ReadOctets(1, &temp, 0, stream); 882 } 883 884 /***********************************************************/ 885 /*=========================================================*/ 886 /*============ ENCODING ROUTINES (Generic PER) ============*/ 887 /*=========================================================*/ 888 /***********************************************************/ 889 890 891 /* --------------------------------------------- */ 892 /* ------------- LOW LEVEL STREAM -------------- */ 893 /* --------------------------------------------- */ 894 895 // ========================================================= 896 // WriteBits() 897 // 898 // This function writes some number of bits to the 899 // output stream. 900 // ========================================================= 901 void WriteBits(uint32 number, uint8 bits, PS_OutStream stream) 902 { 903 uint8 BitSize; 904 uint8 temp; 905 906 BitSize = (uint8)((stream->bitIndex) + number); 907 temp = (uint8)(bits << (8 - number)); 908 (stream->buildByte) |= (temp >> (stream->bitIndex)); 909 910 if (BitSize > 8) /* Appended size > 8 bits */ 911 { 912 stream->bitIndex = 8; 913 WriteRemainingBits(stream); 914 stream->buildByte = (uint8)((bits) << (16 - BitSize)); 915 stream->bitIndex = (uint16)(BitSize - 8); 916 return; 917 } 918 else if (BitSize < 8) /* Appended size < 8 bits */ 919 { 920 stream->bitIndex = BitSize; 921 return; 922 } 923 else /* Appended size == 8 bits */ 924 { 925 stream->bitIndex = 8; 926 WriteRemainingBits(stream); 927 return; 928 } 929 930 } 931 932 // ========================================================= 933 // WriteRemainingBits() 934 // 935 // This function advances to the next octet boundary in 936 // the output stream. Zero-bit padding is done, if needed. 937 // If the stream already points to an octet boundary, no 938 // action is taken. 939 // ========================================================= 940 void WriteRemainingBits(PS_OutStream stream) 941 { 942 if (stream->bitIndex) 943 { 944 if (stream->byteIndex + 1 > stream->size) 945 { 946 ExpandOutStream(stream); 947 } 948 stream->data[stream->byteIndex] = stream->buildByte; 949 ++stream->byteIndex; 950 stream->bitIndex = 0; 951 stream->buildByte = 0; 952 } 953 } 954 955 // ========================================================= 956 // WriteOctets() 957 // 958 // This function writes one or more octets to the output 959 // stream. Input arguments are: 960 // uint32 number; /* Number of octets to write */ 961 // uint8* octets; /* Source for octets */ 962 // uint8 reorder; /* Reorder for little-endian machine? */ 963 // PS_OutStream stream; /* Output stream */ 964 // ========================================================= 965 void WriteOctets(uint32 number, uint8* octets, uint8 reorder, PS_OutStream stream) 966 { 967 uint8* destination; 968 969 WriteRemainingBits(stream); /* Octet alignment */ 970 971 /* Expand the stream, if needed */ 972 while (stream->byteIndex + number > stream->size) 973 { 974 ExpandOutStream(stream); 975 } 976 977 /* Write the octets to stream */ 978 destination = stream->data + stream->byteIndex; 979 if (number == 0) /* No action */ 980 { 981 return; 982 } 983 else if (number <= 4 && reorder) /* Apply reordering */ 984 { 985 switch (number) 986 { 987 case 1: 988 destination[0] = octets[0]; 989 break; 990 case 2: 991 destination[0] = octets[1]; 992 destination[1] = octets[0]; 993 break; 994 case 3: 995 destination[0] = octets[2]; 996 destination[1] = octets[1]; 997 destination[2] = octets[0]; 998 break; 999 case 4: 1000 destination[0] = octets[3]; 1001 destination[1] = octets[2]; 1002 destination[2] = octets[1]; 1003 destination[3] = octets[0]; 1004 break; 1005 } 1006 } 1007 else 1008 { 1009 oscl_memcpy(destination, octets, number); /* Straight copy */ 1010 } 1011 1012 stream->byteIndex = (uint16)(number + stream->byteIndex); 1013 } 1014 1015 // ========================================================= 1016 // NewOutStream() 1017 // 1018 // This function creates a new, empty output stream. 1019 // ========================================================= 1020 PS_OutStream NewOutStream(void) 1021 { 1022 PS_OutStream x; 1023 1024 x = (PS_OutStream) OSCL_DEFAULT_MALLOC(sizeof(S_OutStream)); 1025 x->data = NULL; 1026 x->size = 0; 1027 x->byteIndex = 0; 1028 x->bitIndex = 0; 1029 x->buildByte = 0; 1030 1031 return(x); 1032 } 1033 1034 // ========================================================= 1035 // ExpandOutStream() 1036 // 1037 // This function expands an output stream by some number 1038 // of bytes, as defined by STREAM_ADDITION. 1039 // ========================================================= 1040 void ExpandOutStream(PS_OutStream x) 1041 { 1042 uint8* tmp = x->data; 1043 1044 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size + STREAM_ADDITION); 1045 oscl_memcpy(x->data, tmp, x->size); 1046 if (tmp) 1047 OSCL_DEFAULT_FREE(tmp); 1048 1049 x->size += STREAM_ADDITION; 1050 } 1051 1052 // ========================================================= 1053 // FreeOutStream() 1054 // 1055 // This function frees an existing output stream. 1056 // ========================================================= 1057 void FreeOutStream(PS_OutStream x) 1058 { 1059 OSCL_DEFAULT_FREE(x->data); 1060 OSCL_DEFAULT_FREE(x); 1061 } 1062 1063 /* ----------------------------------------------- */ 1064 /* ------------- HIGH LEVEL ASN DATA ------------- */ 1065 /* ----------------------------------------------- */ 1066 1067 // ========================================================= 1068 // PutBoolean() 1069 // 1070 // This function writes a boolean to the output stream. 1071 // ========================================================= 1072 void PutBoolean(uint32 value, PS_OutStream stream) 1073 { 1074 WriteBits(1, (uint8)value, stream); 1075 } 1076 1077 // ========================================================= 1078 // PutInteger() X.691 Section 10.5 1079 // 1080 // This function encodes a constrained integer, given the 1081 // lower/upper bounds. Note that bounds and value must be 1082 // uint32. This means 0<= {lower,upper,value} <=4294967295. 1083 // Assumes ALIGNED variant of PER. 1084 // ========================================================= 1085 void PutInteger(uint32 lower, uint32 upper, uint32 value, PS_OutStream stream) 1086 { 1087 uint32 range, offset; 1088 uint8 nbits, nbytes = 0; 1089 uint8 code_nbytes; 1090 1091 if (lower > upper) 1092 { 1093 ErrorMessageAndLeave("PutInteger(): Negative range."); 1094 return; 1095 } 1096 if (value < lower) 1097 { 1098 ErrorMessageAndLeave("PutInteger(): Value too small."); 1099 return; 1100 } 1101 if (value > upper) 1102 { 1103 ErrorMessageAndLeave("PutInteger(): Value too large."); 1104 return; 1105 } 1106 1107 range = upper - lower + 1; 1108 offset = value - lower; 1109 1110 if (range == 0 || range > 65536) /* Range exceeds 2-octets */ 1111 { 1112 /* (Range==0 means [0,2^32-1] case) */ 1113 if (offset < 256) nbytes = 1; /* Send using minimum #octets */ 1114 else if (offset < 65536) nbytes = 2; 1115 else if (offset < 16777216) nbytes = 3; 1116 else nbytes = 4; 1117 code_nbytes = (uint8)(nbytes - 1); 1118 WriteBits(2, code_nbytes, stream); /* Send #octets */ 1119 WriteOctets(nbytes, (uint8*)&offset, 1, stream); /* Offset value */ 1120 return; 1121 } 1122 else if (range == 1) /* 0-bits */ 1123 return; 1124 else if (range < 256) /* Bit-field cases */ 1125 { 1126 if (range <= 2) nbits = 1; 1127 else if (range <= 4) nbits = 2; 1128 else if (range <= 8) nbits = 3; 1129 else if (range <= 16) nbits = 4; 1130 else if (range <= 32) nbits = 5; 1131 else if (range <= 64) nbits = 6; 1132 else if (range <= 128) nbits = 7; 1133 else nbits = 8; 1134 WriteBits(nbits, (uint8)offset, stream); 1135 return; 1136 } 1137 else if (range == 256) /* One octet */ 1138 { 1139 WriteOctets(1, (uint8*)(&offset), 1, stream); 1140 return; 1141 } 1142 else /* range<=65536; Two octet */ 1143 { 1144 WriteOctets(2, (uint8*)(&offset), 1, stream); 1145 return; 1146 } 1147 } 1148 1149 // ========================================================= 1150 // PutSignedInteger() X.691 Section 10.5 1151 // 1152 // This function encodes a constrained integer, given the 1153 // lower/upper bounds. The only difference from 1154 // PutInteger() is that the bounds and the values are 1155 // of type int32, and so may be negative. 1156 // Assumes ALIGNED variant of PER. 1157 // ========================================================= 1158 void PutSignedInteger(int32 lower, int32 upper, int32 value, PS_OutStream stream) 1159 { 1160 int32 range, offset; 1161 uint8 nbits, nbytes = 0; 1162 uint8 code_nbytes; 1163 1164 if (lower > upper) 1165 { 1166 ErrorMessageAndLeave("PutSignedInteger(): Negative range."); 1167 return; 1168 } 1169 if (value < lower) 1170 { 1171 ErrorMessageAndLeave("PutSignedInteger(): Value too small."); 1172 return; 1173 } 1174 if (value > upper) 1175 { 1176 ErrorMessageAndLeave("PutSignedInteger(): Value too large."); 1177 return; 1178 } 1179 1180 range = upper - lower + 1; 1181 offset = value - lower; 1182 1183 if (range == 0 || range > 65536) /* Range exceeds 2-octets */ 1184 { 1185 /* (Range==0 means [0,2^32-1] case) */ 1186 if (offset < 256) nbytes = 1; /* Send using minimum #octets */ 1187 else if (offset < 65536) nbytes = 2; 1188 else if (offset < 16777216) nbytes = 3; 1189 else nbytes = 4; 1190 code_nbytes = (uint8)(nbytes - 1); 1191 WriteBits(2, code_nbytes, stream); /* Send #octets */ 1192 WriteOctets(nbytes, (uint8*)&offset, 1, stream); /* Offset value */ 1193 return; 1194 } 1195 else if (range == 1) /* 0-bits */ 1196 return; 1197 else if (range < 256) /* Bit-field cases */ 1198 { 1199 if (range <= 2) nbits = 1; 1200 else if (range <= 4) nbits = 2; 1201 else if (range <= 8) nbits = 3; 1202 else if (range <= 16) nbits = 4; 1203 else if (range <= 32) nbits = 5; 1204 else if (range <= 64) nbits = 6; 1205 else if (range <= 128) nbits = 7; 1206 else nbits = 8; 1207 WriteBits(nbits, (uint8)offset, stream); 1208 return; 1209 } 1210 else if (range == 256) /* One octet */ 1211 { 1212 WriteOctets(1, (uint8*)(&offset), 1, stream); 1213 return; 1214 } 1215 else /* range<=65536; Two octet */ 1216 { 1217 WriteOctets(2, (uint8*)(&offset), 1, stream); 1218 return; 1219 } 1220 } 1221 1222 // ========================================================= 1223 // PutUnboundedInteger() X.691 Section 12 1224 // and also 10.4, 10.9. 1225 // 1226 // This function encodes an unbounded integer, which we 1227 // currently assume has type uint32. We'd need to make 1228 // special arrangements if negative values are allowed. 1229 // Assumes ALIGNED variant of PER. 1230 // ========================================================= 1231 void PutUnboundedInteger(uint32 value, PS_OutStream stream) 1232 { 1233 uint32 nbytes; 1234 1235 /* The encoding is min-octets, and so depends on value */ 1236 if (value < 128) 1237 nbytes = 1; 1238 else if (value < 32768) 1239 nbytes = 2; 1240 else if (value < 8388608) 1241 nbytes = 3; 1242 else 1243 nbytes = 4; 1244 1245 /* Send length det, followed by 2's complement encoding */ 1246 PutLengthDet(nbytes, stream); 1247 WriteOctets(nbytes, (uint8*)(&value), 1, stream); 1248 } 1249 1250 // ========================================================= 1251 // PutExtendedInteger() X.691 Section 12.1 1252 // 1253 // This function encodes a constrained integer with an 1254 // extended range. We assume the value is unsigned, and 1255 // that the ALIGNED variant of PER is used. 1256 // ========================================================= 1257 void PutExtendedInteger(uint32 lower, uint32 upper, uint32 value, PS_OutStream stream) 1258 { 1259 if (value > upper) // Extension ON 1260 { 1261 WriteBits(1, 1, stream); 1262 PutUnboundedInteger(value, stream); 1263 } 1264 else // Extension OFF 1265 { 1266 WriteBits(1, 0, stream); 1267 PutInteger(lower, upper, value, stream); 1268 } 1269 } 1270 1271 // ========================================================= 1272 // PutOctetString() X.691 Section 16 1273 // 1274 // This function writes an OCTET STRING to the output stream. 1275 // Bounds on the size, if any, are included in the input 1276 // arguments. The OCTETSTRING structure (x) is freed at 1277 // the end. 1278 // ========================================================= 1279 void PutOctetString(uint8 unbounded, uint32 min, uint32 max, 1280 PS_OCTETSTRING x, PS_OutStream stream) 1281 { 1282 if (unbounded) /* ====Size is unbounded==== */ 1283 { 1284 PutLengthDet(x->size, stream); 1285 WriteOctets(x->size, x->data, 0, stream); 1286 } 1287 else /* ====Size is bounded==== */ 1288 { 1289 1290 if (min > max) /* Error handling */ 1291 { 1292 ErrorMessageAndLeave("PutOctetString(): Constraint error (min>max)"); 1293 } 1294 else if ((x->size < min) || (x->size > max)) 1295 { 1296 ErrorMessageAndLeave("PutOctetString(): Size out of bounds"); 1297 } 1298 1299 if (min == max) /* Fixed size (no length det!) */ 1300 { 1301 if (x->size > 2) 1302 { 1303 WriteOctets(x->size, x->data, 0, stream); 1304 } 1305 else if (x->size == 2) 1306 { 1307 WriteBits(8, x->data[0], stream); 1308 WriteBits(8, x->data[1], stream); 1309 } 1310 else if (x->size == 1) 1311 { 1312 WriteBits(8, x->data[0], stream); 1313 } 1314 } 1315 else /* Constrained size */ 1316 { 1317 PutInteger(min, max, x->size, stream); 1318 WriteOctets(x->size, x->data, 0, stream); 1319 } 1320 } 1321 } 1322 1323 // ========================================================= 1324 // PutBitString() X.691 Section 16 1325 // 1326 // This function writes a BIT STRING to the output stream. 1327 // Bounds on the size, if any, are included in the input 1328 // arguments. The BITSTRING structure (x) is freed at 1329 // the end. 1330 // ========================================================= 1331 void PutBitString(uint8 unbounded, uint32 min, uint32 max, 1332 PS_BITSTRING x, PS_OutStream stream) 1333 { 1334 uint32 count; 1335 uint8* temp; 1336 1337 count = x->size; 1338 temp = x->data; 1339 1340 if (unbounded) /* ====Size is unbounded==== */ 1341 { 1342 PutLengthDet(x->size, stream); 1343 while (count >= 8) 1344 { 1345 WriteBits(8, temp[0], stream); 1346 ++temp; 1347 count -= 8; 1348 } 1349 WriteBits(count, (uint8)(temp[0] >> (8 - count)), stream); 1350 } 1351 else /* ====Size is bounded==== */ 1352 { 1353 1354 if (min > max) /* Error handling */ 1355 { 1356 ErrorMessageAndLeave("PutBitString(): Constraint error (min>max)"); 1357 } 1358 else if ((x->size < min) || (x->size > max)) 1359 { 1360 ErrorMessageAndLeave("PutBitString(): Size out of bounds"); 1361 } 1362 1363 if (min == max) /* Fixed size (no length det!) */ 1364 { 1365 if (x->size > 16) 1366 { 1367 WriteRemainingBits(stream); /* Octet align */ 1368 } 1369 while (count >= 8) 1370 { 1371 WriteBits(8, temp[0], stream); 1372 ++temp; 1373 count -= 8; 1374 } 1375 WriteBits(count, (uint8)(temp[0] >> (8 - count)), stream); 1376 } 1377 else /* Constrained size */ 1378 { 1379 PutInteger(min, max, x->size, stream); 1380 WriteRemainingBits(stream); 1381 while (count >= 8) 1382 { 1383 WriteBits(8, temp[0], stream); 1384 ++temp; 1385 count -= 8; 1386 } 1387 WriteBits(count, (uint8)(temp[0] >> (8 - count)), stream); 1388 } 1389 } 1390 } 1391 1392 // ========================================================= 1393 // PutCharString() (RAN-UII) 1394 // 1395 // This function encodes a character string to a stream. 1396 // Currently it only handles the special case of DTMF user 1397 // input (that is, signalType in UserInputIndication). 1398 // However, it should be straightforward to extend this 1399 // to handle generic restrictions on the four common 1400 // types (IA5String, NumericString, PrintableString, 1401 // and VisibleString). See X.691 Clause 26.5 for details. 1402 // ========================================================= 1403 void PutCharString(const char *stringName, 1404 uint8 unbounded, uint32 min, uint32 max, const char *from, 1405 PS_int8STRING x, PS_OutStream stream) 1406 { 1407 if (oscl_strncmp(stringName, "IA5String", oscl_strlen("IA5String")) == 0 && // Validate DTMF UII case 1408 unbounded == 0 && 1409 min == 1 && 1410 max == 1 && 1411 oscl_strncmp(from, "0123456789#*ABCD!", oscl_strlen("0123456789#*ABCD!")) == 0) 1412 { 1413 WriteBits(8, x->data[0], stream); // Write single character, 1414 // Normal ascii value, not octet aligned 1415 } 1416 else if (oscl_strncmp(stringName, "GeneralString", oscl_strlen("GeneralString")) == 0) // Validate GeneralString case (RAN-ALPHA) 1417 // ------------------------------------------------------------------------ 1418 // Note on GeneralString: as far as I can tell this is treated as a 1419 // restricted character string type which is not a known-multiplier character 1420 // string. As such it falls under clause 26.6 of X.691. In this case, any 1421 // constraints passed from the PER encoder are not considered 'PER-visible' 1422 // and so they are not used. Because of this, the following should be a 1423 // complete implementation of GeneralString (regardless of constraints). 1424 // It should work for alphanumeric, and anything else that would use 1425 // GeneralString. 1426 // ------------------------------------------------------------------------ 1427 // Note also: I assume you need to install the primary graphic character 1428 // set described in T.51, i.e. that there is no default character set. 1429 // Invoking a character set means sending an escape code. Whether you NEED 1430 // this to get the primary character set wasn't made clear in T.51 1431 // itself, though I found a hint elsewhere that suggested you have to send 1432 // the escape code. The escape code is 27 40 66 15 (or in T.51 lingo, 1433 // "ESC 2/8 4/2 0/15"). Sending this code shouldn't hurt anything if the 1434 // receiving end is compliant to T.51, but if it doesn't work on the first 1435 // try, then one thing you guys might try is removing the escape code, in 1436 // case maybe the VIG is choking on it. Comment out the relevant four lines 1437 // below, and also get rid of the extra '4+' in the length calculation. 1438 // BTW, the escape sequence breaks down into: 1439 // "Designate primary T.51 character set as G0" -- 27 40 66 1440 // "Invoke G0 as the current character set" -- 15 1441 // ------------------------------------------------------------------------ 1442 { 1443 // Encode length of string, in octets 1444 PutLengthDet((x->size), stream); // Assumes 4-byte T.51 escape sequence 1445 // Remove the '4+' if the escape sequence is removed. 1446 // Note: PutLengthDet() does octet alignment for us 1447 // Send the T.51 encoded character data 1448 WriteOctets(x->size, x->data, 1, stream); 1449 } 1450 else 1451 { 1452 ErrorMessageAndLeave("PutCharString(): Not fully implemented."); 1453 } 1454 } 1455 1456 // ========================================================= 1457 // PutObjectID() X.691 Section 23 1458 // 1459 // This function writes an OBJECT IDENTIFIER to the output 1460 // stream. This is just a length determinant, followed by 1461 // a variable number of octets. The OBJECTID structure is 1462 // freed at the end. 1463 // ========================================================= 1464 void PutObjectID(PS_OBJECTIDENT x, PS_OutStream stream) 1465 { 1466 PutLengthDet(x->size, stream); 1467 WriteOctets(x->size, x->data, 0, stream); 1468 } 1469 1470 // ========================================================= 1471 // PutExtensionNull() 1472 // 1473 // This function encodes a NULL object as an extension. 1474 // ========================================================= 1475 void PutExtensionNull(PS_OutStream stream) 1476 { 1477 uint8 temp = 0; 1478 1479 PutLengthDet(1, stream); /* Length wrapper */ 1480 WriteOctets(1, &temp, 0, stream); /* Empty octet */ 1481 } 1482 1483 // ========================================================= 1484 // PutExtensionBoolean() 1485 // 1486 // This function encodes a boolean as an extension. 1487 // ========================================================= 1488 void PutExtensionBoolean(uint32 value, PS_OutStream stream) 1489 { 1490 PutLengthDet(1, stream); /* Length wrapper */ 1491 PutBoolean(value, stream); /* Boolean */ 1492 WriteRemainingBits(stream); /* Complete the octet */ 1493 } 1494 1495 // ========================================================= 1496 // PutExtensionInteger() 1497 // 1498 // This function encodes an integer as an extension. 1499 // ========================================================= 1500 void PutExtensionInteger(uint32 lower, uint32 upper, uint32 value, PS_OutStream stream) 1501 { 1502 PS_OutStream tempStream; 1503 1504 tempStream = NewOutStream(); /* Create a temp stream */ 1505 PutInteger(lower, upper, value, tempStream); /* Write integer to temp */ 1506 PutTempStream(tempStream, stream); /* Transmit contents of tempStream */ 1507 } 1508 1509 // ========================================================= 1510 // PutExtensionOctetString() 1511 // 1512 // This function encodes an octet string as an extension. 1513 // ========================================================= 1514 void PutExtensionOctetString(uint8 unbounded, 1515 uint32 min, uint32 max, PS_OCTETSTRING x, PS_OutStream stream) 1516 { 1517 PS_OutStream tempStream; 1518 1519 tempStream = NewOutStream(); /* Create a temp stream */ 1520 PutOctetString(unbounded, min, max, x, tempStream); /* Write to temp */ 1521 PutTempStream(tempStream, stream); /* Transmit contents of tempStream */ 1522 } 1523 1524 1525 /* --------------------------------------------- */ 1526 /* ---------------- OTHER CALLS -----------------*/ 1527 /* --------------------------------------------- */ 1528 1529 // ========================================================= 1530 // PutNormSmallValue() X.691 Section 10.6 1531 // 1532 // Sends a normally small nonnegative value. Range is 1533 // [0,infinity]. (In CHOICE, this sends the choice index 1534 // when extension is ON). 1535 // Assumes ALIGNED variant of PER. 1536 // ========================================================= 1537 void PutNormSmallValue(uint32 value, PS_OutStream stream) 1538 { 1539 uint8 sendval; 1540 if (value < 64) 1541 { 1542 sendval = (uint8) value; 1543 WriteBits(7, sendval, stream); 1544 } 1545 else 1546 { 1547 ErrorMessageAndLeave("PutNormSmallValue(): range exceeded."); 1548 } 1549 } 1550 1551 // ========================================================= 1552 // PutChoiceIndex() X.691 Sections 22.4 - 22.8 1553 // 1554 // Writes the extension bit (if needed) and the choice index 1555 // to the bitstream. Assumes ALIGNED variant of PER. 1556 // 1557 // Inputs: rootnum (number of items in root) 1558 // extmarker (0 if no extension marker, 1 otherwise) 1559 // index (choice index, possibly extended) 1560 // ========================================================= 1561 void PutChoiceIndex(uint32 rootnum, uint8 extmarker, uint32 index, 1562 PS_OutStream stream) 1563 { 1564 if (!extmarker) /* ---Extension marker NOT present --- */ 1565 { 1566 PutInteger(0, rootnum - 1, (uint32)index, stream); 1567 } 1568 else /* ---Extension marker present --- */ 1569 { 1570 if (index < rootnum) 1571 { 1572 WriteBits(1, 0, stream); /* Extension bit OFF */ 1573 PutInteger(0, rootnum - 1, (uint32)index, stream); 1574 } 1575 else 1576 { 1577 WriteBits(1, 1, stream); /* Extension bit ON */ 1578 PutNormSmallValue((uint32)(index - rootnum), stream); 1579 } 1580 } 1581 } 1582 1583 // ========================================================= 1584 // PutNormSmallLength() X.691 Section 10.9.3.4 1585 // 1586 // Sends a normally small length determinant. Range is 1587 // [1,infinity]. (For SEQUENCE, this sends the size of 1588 // the SigMap for unknown extensions.) 1589 // Assumes ALIGNED variant of PER. 1590 // ========================================================= 1591 void PutNormSmallLength(uint32 value, PS_OutStream stream) 1592 { 1593 uint8 sendval; 1594 if (value < 65) 1595 { 1596 sendval = (uint8)(value - 1); 1597 WriteBits(7, sendval, stream); 1598 } 1599 else 1600 { 1601 ErrorMessageAndLeave("PutNormSmallLength(): range exceeded."); 1602 } 1603 } 1604 1605 // ========================================================= 1606 // PutLengthDet() X.691 Section 10.9 1607 // 1608 // Encodes a general length determinant to the output stream. 1609 // (e.g. for extension wrapper). 1610 // Assumes ALIGNED variant of PER. 1611 // ========================================================= 1612 void PutLengthDet(uint32 value, PS_OutStream stream) 1613 { 1614 uint8 byte; 1615 uint16 bytes; 1616 uint16 mask = 0x8000; /* 10000000 00000000 */ 1617 1618 if (value < 128) /* One octet with leading '0' */ 1619 { 1620 byte = (uint8) value; 1621 WriteOctets(1, &byte, 0, stream); 1622 } 1623 else if (value < 16384) /* Two octets with leading '10' */ 1624 { 1625 bytes = (uint16)(value | mask); 1626 WriteOctets(2, (uint8*)&bytes, 0, stream); 1627 } 1628 else 1629 { 1630 ErrorMessageAndLeave("PutLengthDet(): Fragmented Length Dets Not Supported."); 1631 } 1632 } 1633 1634 // ========================================================= 1635 // PutExtensionItem() 1636 // 1637 // This function writes an extension item, including the 1638 // length wrapper. It makes a generic call to one of the 1639 // H.245-defined PER Encoder routines. 1640 // ========================================================= 1641 void PutExtensionItem( 1642 void (*Func)(uint8* data, PS_OutStream stream), 1643 uint8* x, PS_OutStream stream) 1644 { 1645 PS_OutStream tempStream; 1646 1647 tempStream = NewOutStream(); /* Create a temp stream */ 1648 Func(x, tempStream); /* Encode x, writing to tempStream */ 1649 PutTempStream(tempStream, stream); /* Transmit contents of tempStream */ 1650 } 1651 1652 // ========================================================= 1653 // PutTempStream() 1654 // 1655 // This function copies the contents of a temporary output 1656 // stream (tempStream) to the main output stream (stream), 1657 // preceeded by a generial length determinant. 1658 // It also frees tempStream at the end. 1659 // ========================================================= 1660 void PutTempStream(PS_OutStream tempStream, PS_OutStream stream) 1661 { 1662 WriteRemainingBits(tempStream); 1663 PutLengthDet(tempStream->byteIndex, stream); /* Copy to real stream */ 1664 WriteOctets(tempStream->byteIndex, tempStream->data, 0, stream); 1665 FreeOutStream(tempStream); 1666 } 1667 1668 /********************************************************/ 1669 /*======================================================*/ 1670 /*============ OTHER ROUTINES (Generic PER) ============*/ 1671 /*======================================================*/ 1672 /********************************************************/ 1673 1674 // ========================================================= 1675 // ConvertOutstreamToInstream() 1676 // 1677 // This function creates a new InStream and copies into 1678 // it the contents of an old OutStream. This is useful 1679 // for internal testing. 1680 // Note that the outstream is destroyed in the process. 1681 // ========================================================= 1682 PS_InStream ConvertOutstreamToInstream(PS_OutStream outstream) 1683 { 1684 PS_InStream instream; 1685 1686 WriteRemainingBits(outstream); 1687 instream = (PS_InStream) OSCL_DEFAULT_MALLOC(sizeof(S_InStream)); 1688 instream->data = outstream->data; 1689 instream->bitIndex = 0; 1690 1691 OSCL_DEFAULT_FREE(outstream); 1692 return(instream); 1693 } 1694 1695 // ========================================================= 1696 // NewOctetString() 1697 // 1698 // This function creates a new OCTETSTRING. 1699 // For now, the data field just contains the string 1700 // "OctetString". 1701 // Later, I'll add input parameters and construct the 1702 // real thing. 1703 // THIS ROUTINE NEEDS ATTENTION! 1704 // ========================================================= 1705 PS_OCTETSTRING NewOctetString(void) 1706 { 1707 PS_OCTETSTRING x; 1708 1709 x = (PS_OCTETSTRING) OSCL_DEFAULT_MALLOC(sizeof(S_OCTETSTRING)); 1710 x->size = 12; 1711 x->data = (uint8*) OSCL_DEFAULT_MALLOC(12 * sizeof(uint8)); 1712 oscl_strncpy((char *) x->data, "OctetString", x->size); 1713 1714 return(x); 1715 } 1716 1717 // ========================================================= 1718 // NewBitString() 1719 // 1720 // This function creates a new BITSTRING. 1721 // For now, the data field just contains the string 1722 // "BitString". 1723 // Later, I'll add input parameters and construct the 1724 // real thing. 1725 // THIS ROUTINE NEEDS ATTENTION! 1726 // ========================================================= 1727 PS_BITSTRING NewBitString(void) 1728 { 1729 PS_BITSTRING x; 1730 1731 x = (PS_BITSTRING) OSCL_DEFAULT_MALLOC(sizeof(S_BITSTRING)); 1732 x->size = 10; 1733 x->data = (uint8*) OSCL_DEFAULT_MALLOC(10 * sizeof(uint8)); 1734 oscl_strncpy((char *) x->data, "BitString", x->size); 1735 1736 return(x); 1737 } 1738 1739 // ========================================================= 1740 // NewCharString() 1741 // 1742 // This function creates a new int8STRING. 1743 // For now, the data field just contains the string 1744 // "CharString". 1745 // Later, I'll add input parameters and construct the 1746 // real thing. 1747 // THIS ROUTINE NEEDS ATTENTION! 1748 // ========================================================= 1749 PS_int8STRING NewCharString(void) 1750 { 1751 PS_int8STRING x; 1752 1753 x = (PS_int8STRING) OSCL_DEFAULT_MALLOC(sizeof(S_int8STRING)); 1754 x->size = 11; 1755 x->data = (uint8*) OSCL_DEFAULT_MALLOC(11 * sizeof(uint8)); 1756 oscl_strncpy((char *) x->data, "CharString", x->size); 1757 1758 return(x); 1759 } 1760 1761 // ========================================================= 1762 // NewObjectID() 1763 // 1764 // This function creates a new OBJECTID. 1765 // For now, the ID just contains the string "Object ID". 1766 // Later, I'll add input parameters and construct the 1767 // real thing. 1768 // THIS ROUTINE NEEDS ATTENTION! 1769 // ========================================================= 1770 PS_OBJECTIDENT NewObjectID(void) 1771 { 1772 PS_OBJECTIDENT x; 1773 1774 x = (PS_OBJECTIDENT) OSCL_DEFAULT_MALLOC(sizeof(S_OBJECTIDENT)); 1775 x->size = 10; 1776 x->data = (uint8*) OSCL_DEFAULT_MALLOC(10 * sizeof(uint8)); 1777 oscl_strncpy((char *) x->data, "Object ID", x->size); 1778 1779 return(x); 1780 } 1781 1782 // ========================================================= 1783 // InitOctetString() 1784 // 1785 // This function inits a previously allocated OCTET STRING. 1786 // For now, the data field just contains the string 1787 // "OctetString". 1788 // Later, I'll add input parameters and construct the 1789 // real thing. 1790 // THIS ROUTINE NEEDS ATTENTION! 1791 // ========================================================= 1792 void InitOctetString(PS_OCTETSTRING x) 1793 { 1794 x->size = 12; 1795 x->data = (uint8*) OSCL_DEFAULT_MALLOC(12 * sizeof(uint8)); 1796 oscl_strncpy((char *) x->data, "OctetString", x->size); 1797 } 1798 1799 // ========================================================= 1800 // InitBitString() 1801 // 1802 // This function inits a previously allocated BIT STRING. 1803 // For now, the data field just contains the string 1804 // "BitString". 1805 // Later, I'll add input parameters and construct the 1806 // real thing. 1807 // THIS ROUTINE NEEDS ATTENTION! 1808 // ========================================================= 1809 void InitBitString(PS_BITSTRING x) 1810 { 1811 x->size = 10; 1812 x->data = (uint8*) OSCL_DEFAULT_MALLOC(10 * sizeof(uint8)); 1813 oscl_strncpy((char *) x->data, "BitString", x->size); 1814 } 1815 1816 // ========================================================= 1817 // InitCharString() 1818 // 1819 // This function inits a previously allocated int8 STRING. 1820 // For now, the data field just contains the string 1821 // "CharString". 1822 // Later, I'll add input parameters and construct the 1823 // real thing. 1824 // THIS ROUTINE NEEDS ATTENTION! 1825 // ========================================================= 1826 void InitCharString(PS_int8STRING x) 1827 { 1828 x->size = 11; 1829 x->data = (uint8*) OSCL_DEFAULT_MALLOC(11 * sizeof(uint8)); 1830 oscl_strncpy((char *) x->data, "CharString", x->size); 1831 } 1832 1833 // ========================================================= 1834 // InitObjectid() 1835 // 1836 // This function inits a previously allocated OBJECT IDENTIFIER. 1837 // For now, the data field just contains the string 1838 // "ObjectID". 1839 // Later, I'll add input parameters and construct the 1840 // real thing. 1841 // THIS ROUTINE NEEDS ATTENTION! 1842 // ========================================================= 1843 void InitObjectid(PS_OBJECTIDENT x) 1844 { 1845 x->size = 9; 1846 x->data = (uint8*) OSCL_DEFAULT_MALLOC(9 * sizeof(uint8)); 1847 oscl_strncpy((char *) x->data, "ObjectID", x->size); 1848 } 1849 1850 // ========================================================= 1851 // FreeOctetString() 1852 // 1853 // This frees an OCTET STRING. 1854 // ========================================================= 1855 void FreeOctetString(PS_OCTETSTRING x) 1856 { 1857 if (x->size > 0) 1858 { 1859 OSCL_DEFAULT_FREE(x->data); 1860 } 1861 OSCL_DEFAULT_FREE(x); 1862 } 1863 1864 // ========================================================= 1865 // FreeBitString() 1866 // 1867 // This frees a BIT STRING. 1868 // ========================================================= 1869 void FreeBitString(PS_BITSTRING x) 1870 { 1871 OSCL_DEFAULT_FREE(x->data); 1872 OSCL_DEFAULT_FREE(x); 1873 } 1874 1875 // ========================================================= 1876 // FreeCharString() 1877 // 1878 // This frees a int8 STRING. 1879 // ========================================================= 1880 void FreeCharString(PS_int8STRING x) 1881 { 1882 if (x->data) 1883 { 1884 OSCL_DEFAULT_FREE(x->data); 1885 } 1886 OSCL_DEFAULT_FREE(x); 1887 } 1888 1889 // ========================================================= 1890 // FreeObjectID() 1891 // 1892 // This frees an OBJECT IDENTIFIER. 1893 // ========================================================= 1894 void FreeObjectID(PS_OBJECTIDENT x) 1895 { 1896 if (x->data) 1897 OSCL_DEFAULT_FREE(x->data); 1898 OSCL_DEFAULT_FREE(x); 1899 } 1900 1901 1902