Wrapper for a byte[]. May appear as values read from and written to AMQP field tables.

The sole reason for the existence of this class is to permit encoding of byte[] as 'x' in AMQP field tables, an extension to the specification that is part of the tentative JMS mapping implemented by QPid.

Instances of this object may be found as values held in IDictionary instances returned from RabbitMQ.Client.Impl.WireFormatting.ReadTable, e.g. as part of IBasicProperties.Headers tables. Likewise, instances may be set as values in an IDictionary table to be encoded by RabbitMQ.Client.Impl.WireFormatting.WriteTable.

When an instance of this class is encoded/decoded, the type tag 'x' is used in the on-the-wire representation. The AMQP standard type tag 'S' is decoded to a raw byte[], and a raw byte[] is encoded as 'S'. Instances of System.String are converted to a UTF-8 binary representation, and then encoded using tag 'S'. In order to force the use of tag 'x', instances of this class must be used.

        public static object ReadFieldValue(NetworkBinaryReader reader)
        {
            object value = null;
            byte discriminator = reader.ReadByte();
            switch ((char)discriminator)
                {
                  case 'S':
                      value = ReadLongstr(reader);
                      break;
                  case 'I':
                      value = reader.ReadInt32();
                      break;
                  case 'D':
                      value = ReadDecimal(reader);
                      break;
                  case 'T':
                      value = ReadTimestamp(reader);
                      break;
                  case 'F':
                      value = ReadTable(reader);
                      break;

                  case 'A':
                      value = ReadArray(reader);
                      break;
                  case 'b':
                      value = ReadOctet(reader);
                      break;
                  case 'd':
                      value = reader.ReadDouble();
                      break;
                  case 'f':
                      value = reader.ReadSingle();
                      break;
                  case 'l':
                      value = reader.ReadInt64();
                      break;
                  case 's':
                      value = reader.ReadInt16();
                      break;
                  case 't':
                      value = (ReadOctet(reader) != 0);
                      break;
                  case 'x':
                      value = new BinaryTableValue(ReadLongstr(reader));
                      break;
                  case 'V':
                      value = null;
                      break;

                  default:
                      throw new SyntaxError("Unrecognised type in table: " +
                                            (char) discriminator);
                }
            return value;
        }
Пример #2
0
        private object ConvertHeaderValueIfNecessary(object valueArg)
        {
            var value = valueArg;

            if (value == null)
            {
                return(value);
            }

            var valid = (value is string) || (value is byte[]) ||
                        (value is bool) || (value is byte) || (value is sbyte) ||
                        (value is uint) || (value is int) || (value is long) ||
                        (value is float) || (value is double) || (value is decimal) ||
                        (value is short) || (value is RC.AmqpTimestamp) ||
                        (value is IList) || (value is IDictionary) || (value is RC.BinaryTableValue) ||
                        (value is object[]) || (value is Type);

            if (!valid)
            {
                value = value.ToString();
            }
            else if (value is object[] array)
            {
                var writableList = new object[array.Length];
                for (var i = 0; i < array.Length; i++)
                {
                    writableList[i] = ConvertHeaderValueIfNecessary(array[i]);
                }

                value = writableList;
            }
            else if (value is IList list)
            {
                var writableList = new List <object>();
                foreach (var listValue in list)
                {
                    writableList.Add(ConvertHeaderValueIfNecessary(listValue));
                }

                value = writableList;
            }
            else if (value is IDictionary originalMap)
            {
                var writableMap = new Dictionary <object, object>();
                foreach (DictionaryEntry entry in originalMap)
                {
                    writableMap[entry.Key] = ConvertHeaderValueIfNecessary(entry.Value);
                }

                value = writableMap;
            }
            else if (value is Type type)
            {
                value = type.ToString();
            }
            else if (value is byte[] v)
            {
                value = new RC.BinaryTableValue(v);
            }

            return(value);
        }
Пример #3
0
        public static int Main(string[] args)
        {
            bool persistMode = false;

            int optionIndex = 0;
            while (optionIndex < args.Length) {
                if (args[optionIndex] == "/persist") {
                    persistMode = true;
                } else {
                    break;
                }
                optionIndex++;
            }

            if (((args.Length - optionIndex) < 1) ||
                (((args.Length - optionIndex - 1) % 2) == 1))
                {
                    Console.Error.WriteLine("Usage: SendMap [<option> ...] <exchange-uri> [[<key> <value>] ...]");
                    Console.Error.WriteLine("RabbitMQ .NET client version "+typeof(IModel).Assembly.GetName().Version.ToString());
                    Console.Error.WriteLine("Exchange-URI: amqp://host[:port]/exchange[/routingkey][?type=exchangetype]");
                    Console.Error.WriteLine("Keys must start with '+' or with '-'. Those starting with '+' are placed in");
                    Console.Error.WriteLine("the body of the message, and those starting with '-' are placed in the headers.");
                    Console.Error.WriteLine("Values must start with a single character typecode and a colon.");
                    Console.Error.WriteLine("Supported typecodes are:");
                    Console.Error.WriteLine(" S - string/byte array");
                    Console.Error.WriteLine(" x - byte array (base-64)");
                    Console.Error.WriteLine(" t - boolean");
                    Console.Error.WriteLine(" i - 32-bit integer");
                    Console.Error.WriteLine(" d - double-precision float");
                    Console.Error.WriteLine(" D - fixed-point decimal");
                    Console.Error.WriteLine("Note that some types are valid only in the body of a message, and some are");
                    Console.Error.WriteLine("valid only in the headers.");
                    Console.Error.WriteLine("The exchange \"amq.default\" is an alias for the default (\"\") AMQP exchange,");
                    Console.Error.WriteLine("introduced so that the default exchange can be addressed via URI syntax.");
                    Console.Error.WriteLine("Available options:");
                    Console.Error.WriteLine("  /persist     send message in 'persistent' mode");
                    return 2;
                }

            Uri uri = new Uri(args[optionIndex++]);
            string exchange = uri.Segments[1].TrimEnd(new char[] { '/' });
            string exchangeType = uri.Query.StartsWith("?type=") ? uri.Query.Substring(6) : null;
            string routingKey = uri.Segments.Length > 2 ? uri.Segments[2] : "";

            if (exchange == "amq.default") {
                exchange = "";
            }

            ConnectionFactory cf = new ConnectionFactory();
            cf.Endpoint = new AmqpTcpEndpoint(uri);

            using (IConnection conn = cf.CreateConnection())
                {
                    using (IModel ch = conn.CreateModel()) {

                        if (exchangeType != null) {
                            ch.ExchangeDeclare(exchange, exchangeType);
                        }

                        IMapMessageBuilder b = new MapMessageBuilder(ch);
                        while ((optionIndex + 1) < args.Length) {
                            string keyAndDiscriminator = args[optionIndex++];
                            string valueAndType = args[optionIndex++];

                            if (keyAndDiscriminator.Length < 1) {
                                Console.Error.WriteLine("Invalid key: '{0}'", keyAndDiscriminator);
                                return 2;
                            }
                            string key = keyAndDiscriminator.Substring(1);
                            char discriminator = keyAndDiscriminator[0];

                            IDictionary target;
                            switch (discriminator) {
                              case '-':
                                  target = b.Headers;
                                  break;
                              case '+':
                                  target = b.Body;
                                  break;
                              default:
                                  Console.Error.WriteLine("Invalid key: '{0}'",
                                                          keyAndDiscriminator);
                                  return 2;
                            }

                            if (valueAndType.Length < 2 || valueAndType[1] != ':') {
                                Console.Error.WriteLine("Invalid value: '{0}'", valueAndType);
                                return 2;
                            }
                            string valueStr = valueAndType.Substring(2);
                            char typeCode = valueAndType[0];

                            object value;
                            switch (typeCode) {
                              case 'S':
                                  value = valueStr;
                                  break;
                              case 'x':
                                  value = new BinaryTableValue(Convert.FromBase64String(valueStr));
                                  break;
                              case 't':
                                  value = (valueStr.ToLower() == "true" ||
                                           valueStr.ToLower() == "yes" ||
                                           valueStr.ToLower() == "on" ||
                                           valueStr == "1");
                                  break;
                              case 'i':
                                  value = int.Parse(valueStr);
                                  break;
                              case 'd':
                                  value = double.Parse(valueStr);
                                  break;
                              case 'D':
                                  value = decimal.Parse(valueStr);
                                  break;
                              default:
                                  Console.Error.WriteLine("Invalid type code: '{0}'", typeCode);
                                  return 2;
                            }

                            target[key] = value;
                        }
                        if (persistMode) {
                            ((IBasicProperties) b.GetContentHeader()).DeliveryMode = 2;
                        }
                        ch.BasicPublish(exchange,
                                        routingKey,
                                        (IBasicProperties) b.GetContentHeader(),
                                        b.GetContentBody());
                        return 0;
                    }
                }
        }
        ///<summary>Reads an AMQP "table" definition from the reader.</summary>
        ///<remarks>
        /// Supports the AMQP 0-8/0-9 standard entry types S, I, D, T
        /// and F, as well as the QPid-0-8 specific b, d, f, l, s, t,
        /// x and V types.
        ///</remarks>
        public static IDictionary ReadTable(NetworkBinaryReader reader)
        {
            Hashtable table = new Hashtable();
            long tableLength = reader.ReadUInt32();

            Stream backingStream = reader.BaseStream;
            long startPosition = backingStream.Position;
            while ((backingStream.Position - startPosition) < tableLength)
            {
                string key = ReadShortstr(reader);
                object value = null;

                byte discriminator = reader.ReadByte();
                switch ((char)discriminator)
                {
                  case 'S':
                      value = ReadLongstr(reader);
                      break;
                  case 'I':
                      value = reader.ReadInt32();
                      break;
                  case 'D':
                      value = ReadDecimal(reader);
                      break;
                  case 'T':
                      value = ReadTimestamp(reader);
                      break;
                  case 'F':
                      value = ReadTable(reader);
                      break;

                  case 'b':
                      value = ReadOctet(reader);
                      break;
                  case 'd':
                      value = reader.ReadDouble();
                      break;
                  case 'f':
                      value = reader.ReadSingle();
                      break;
                  case 'l':
                      value = reader.ReadInt64();
                      break;
                  case 's':
                      value = reader.ReadInt16();
                      break;
                  case 't':
                      value = (ReadOctet(reader) != 0);
                      break;
                  case 'x':
                      value = new BinaryTableValue(ReadLongstr(reader));
                      break;
                  case 'V':
                      value = null;
                      break;

                  default:
                      throw new SyntaxError("Unrecognised type in table: " +
                                            (char) discriminator);
                }

                if (!table.ContainsKey(key))
                {
                    table[key] = value;
                }
            }

            return table;
        }