WebRTC RTCDataChannel - how to configure to be reliable? - webrtc

I fired up a RTCDataChannel, and, by default it appears to be in unreliable mode.
I want to configure it to be reliable to get guaranteed packet delivery, but the RTCDataChannelInit configuration doesn't seem to have a setting for this.
dictionary RTCDataChannelInit {
boolean ordered = true;
unsigned short maxPacketLifeTime;
unsigned short maxRetransmits;
DOMString protocol = "";
boolean negotiated = false;
unsigned short id;
};
Also, the RTCDataChannel.isReliable is a read-only property.
How do I configure the channel to be in reliable mode?

The default is a reliable channel. See the specification, fourth paragraph in that section.

Related

ServiceStack RedisMqServer: No way to add or remove channels in runtime?

My, already "legacy" by now, implementation of a pub/sub solution using ServiceStack quickly ran out of clients, when it reached the 20 client limit.
We do something like:
_redisConsumer = MqClientFactory.Instance.GetRedisClient(); // Returns a IRedisClient
_subscription = _redisConsumer.CreateSubscription();
_subscription.OnSubscribe = channel => CoreLog.Instance.Info($"Subscription started on {eventChannelName}");
_subscription.OnUnSubscribe = channel => CoreLog.Instance.Warning($"Unsubscribed from {eventChannelName}");
_subscription.OnMessage = (channel, msg) =>
{
try
{
onMessageReceived(CoreRequestJsonEnvelope.CreateCoreRequestFromJson(msg));
}
catch (Exception ex)
{
CoreLog.Instance.Exception(ex);
}
};
// Since it blocks execution, we put this in a Task:
Task.Run(() =>
{
try
{
_subscription.SubscribeToChannels(eventChannelName); // blocking
}
catch(Exception e)
{
}
});
and when we have enough different channels to listen too, it runs out.
I then thought, that maybe instead of taking a new IRedisClient for each subscription, I could use the same IRedisClient for all of them, so:
_redisConsumer = mySavedRedisClient;
...
but that returns Unknown reply on multi-request after a few seconds/executions.
Lastly, I looked at the RedisPubSubServer, but it seems that I need to specify the channels in the constructor, and I cannot change after that. I do need to add and remove channels in runtime, and channels are not known from start.
What is the recommended approach?
Is it to increaase the Max-limit and continue as before?
Is it to use RedisPubSub, but how to handle dynamic channels?
What does "unknown reply on multi-request" actually mean?
Thanks!
It's not clear what 20 client limit you're referring to & how the client limit is dependent on channels or subscribers, but if this is your App own limit than sounds like increasing it would be the easiest solution.
ServiceStack.Redis doesn't support changing the subscribed channels after a subscription has started. Instead of managing the IRedisSubscription yourself you may want to consider ServiceStack.Redis Managed Pub/Sub Server which manages the background subscription thread with added resiliency and support for auto retries.
Whilst you can't change the subscribed channels at runtime, you can modify the modify the Channels collection and restart the subscription to create a new subscription to the updated channels list, e.g:
var pubSub = new RedisPubSubServer(clientsManager, chan1);
pubSub.Start();
//...
pubSub.Channels = new[] { chan1, chan2 };
pubSub.Restart();
Otherwise depending on your use-case you may be able to subscribe to a channel pattern which allows you to subscribe to a multiple dynamic channels matching wildcard channel pattern:
var pubSub = new RedisPubSubServer(clientsManager) {
ChannelsMatching = new[] { "chan:*" }
}
.Start();
Where it will handle any messages clients send that matches the channel pattern.

How to use STM32 lwip/mqtt api with tls?

i made stm32 + rtos + lwip/mqtt solution and it works well. Now i want to use it with embed tls secure connection. I did not find any exemples.
lwip mqtt api supports tls comunication. But there are no such example, just simple mqtt client using code LWIP MQTT Client i used.
I tried to enable embedtls and some options in cubemx, LWIP_ALTCP & LWIP_ALTCP_TLS, add LWIP_ALTCP_TLS_MBEDTLS to Path. It compiled.
How to init mbedtls and add tls cert. this link takes a little info altcp tls
Has anyebody some expirience or working example with stm32 lwip/mqtt + tls (mbedtls) for stm32 lwip stack?
UPD.
Here is my code of mqtt client setup:
struct mqtt_connect_client_info_t ci;
memset(&ci, 0, sizeof(ci));
ci.client_id = "lwip_test";
ci.client_user = "";
ci.client_pass = "";
ci.keep_alive = 0;
ci.tls_config = altcp_tls_create_config_client((const u8_t*)test_cert, sizeof(test_cert));
// create client
client = mqtt_client_new();
// connect client
mqtt_client_connect(client, &resolved, port, mqtt_on_connect, (void *)0, &ci);
I give mqtt client ca certificate and length. I have an error in
altcp_tls_create_config_client_common function (altcp_tls_mbedtls.c) with code -4480 (Failed to allocate memory).
ret = mbedtls_x509_crt_parse(conf->ca, ca, ca_len);
if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse ca failed: %d 0x%x", ret, -1*ret));
altcp_mbedtls_free_config(conf);
return NULL;
}
What i am doing wrong, whitch options else i should set up in mbedtls module?
I use default was generated by CubeMX
This thread helped me together with other examples in https://www.nongnu.org/lwip/2_0_x/group__mqtt.html to make the MQTT client work with MbedTLS 2 way authentication. I can now subscribe/publish to the amazon AWS cloud.
So if anybody is interested, here is what I did.
Generate code from CubeMX with LwIP and MbedTLS enabled. Important is to enable MBEDTLS_PLATFORM_MEMORY, MEMP_MEM_MALLOC and LWIP_ALTCP_TLS_MBEDTLS so the library uses alternative calloc/free functions from LwIP (they are set in the altcp_mbedtls_mem_init() function).
I also use MBEDTLS_ENTROPY_HARDWARE_ALT, MBEDTLS_NO_PLATFORM_ENTROPY and MBEDTLS_CTR_DRBG_C enabled, so the MbedTLS library can use the ctr drbg random number generator (initialized in the altcp_tls_create_config() function).
If you use FreeRTOS with your LwIP as I do, it is necessarry to enable MBEDTLS_THREADING_ALT and then in your code call the mbedtls_threading_set_alt() function to enable mutex handling in the MbedTLS library.
Here is then what I do in my code:
mqtt_client_t *client;
struct mqtt_connect_client_info_t client_info;
ip_addr_t server_ip;
/* Somewhere in the code call this to get IP address of the host */
ip_addr_t ipaddr;
err = dns_gethostbyname("host_name", &ipaddr, mqtt_resolved_cb, NULL);
/* Wait until this callback gets the IP */
static void mqtt_resolved_cb(const char *host, const ip_addr_t *ipaddr,
void *callback_arg)
{
/* If resolved IP is known -> set it */
if (ipaddr->addr != 0)
{
server_ip.addr = ipaddr->addr;
}
}
/* Then call this to start MQTT client */
void mqtt_test(const ip_addr_t *ipaddr, uint16_t port,
const uint8_t *ca_cert_str, size_t ca_cert_len,
const uint8_t *dev_cert_str, size_t dev_cert_len,
const uint8_t *dev_key_str, size_t dev_key_len,
const uint8_t *dev_key_pass_str, size_t dev_key_pass_len)
{
/* Setup an empty client info structure */
memset(&mqtt.client_info, 0, sizeof(mqtt.client_info));
/* Set client information */
mqtt.client_info.client_id = "lwip_test";
mqtt.client_info.client_user = NULL;
mqtt.client_info.client_pass = NULL;
mqtt.client_info.keep_alive = 0;
mqtt.client_info.will_topic = NULL;
mqtt.client_info.will_msg = NULL;
mqtt.client_info.will_retain = 0;
mqtt.client_info.will_qos = 0;
/* Set TLS configuration */
mqtt.client_info.tls_config = altcp_tls_create_config_client_2wayauth(
ca_cert_str, ca_cert_len,
dev_key_str, dev_key_len, dev_key_pass_str, dev_key_pass_len,
dev_cert_str, dev_cert_len);
/* Allocate memory for MQTT client */
mqtt.client = mqtt_client_new();
/* Connect to the server */
if (mqtt.client != NULL)
{
err = mqtt_client_connect(
mqtt.client, ipaddr, port,
mqtt_connection_cb, 0, &mqtt.client_info);
}
}
Then the code continues in the standard mqtt callbacks from the example link above.
Thanks and I hope this can help someone else too.
I have an identical configuration, so I can tell you that if you debug code you'll see that it will crash trying to call calloc, if your environment is equal to mine, you have not that system function.
What I did is using calloc implemented in lwip, in particular into altcp module.
I defined via cubemx MBEDTLS_PLATFORM_MEMORY, in order to activate the define ALTCP_MBEDTLS_PLATFORM_ALLOC in altcp_tls_mbedtls_mem.c, then I was able to use
altcp_mbedtls_mem_init() function that specify to mbedtls to use altcp calloc and free.
This function is called into altcp_tls_create_config_client, so if you are going to use it, you don't have to call altcp_mbedtls_mem_init() twice.
In this way you should be able to correctly allocate memory for mbedtls.
you seem to have a memory allocation problem, you can try to increase the heap memory size in lwipopts.h like the following:
#define MEM_SIZE (50 * 1024)

How to set consumer priority using MassTransit and RabbitMQ

MassTransit exposes functions for adding queue and exchange arguments, but I cannot find anything similar for the consumer.
I would like to be able to set the priority of consumers (x-priority argument) per the RabbitMQ documentation here: https://www.rabbitmq.com/consumer-priority.html
Is that possible using MassTransit?
It should be easy enough to add this to MT, I'll create an issue on GitHub.
According to RabbitMQ documentation:
Set the x-priority argument in the basic.consume method to an integer
value. Consumers which do not specify a value have priority 0.
Larger numbers indicate higher priority, and both positive and
negative numbers can be used.
When you setup consumer you can use ConsumerPriority in this case to set a lower priority
_busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost host = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), h =>
{
h.Username(ConfigurationManager.AppSettings["RabbitMQUsername"]);
h.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
});
cfg.ReceiveEndpoint(host, "Audit", e =>
{
e.PrefetchCount = 2;
e.ConsumerPriority = -1;
e.Consumer<AuditConsumer>();
});
});

Override built-in Redis commands with C modules

I try to override the set Redis built-in command by implementing a module using the Redis API. I would like to publish the set value on a specific channel. notify-keyspace-events KEAg would have been a good solution if the value was sent on the channel but it is not the case.
I also tried to override the set command directly with the API, but RedisModule_CreateCommand seems only work for new commands, not for built-in commands.
I also tried to create a command like setpub and use rename-command SET SETPUB but SETPUB doesn't seem to be recognize, even if we userename-commandafterloadmodule setpub.so`.
Is there a way to override the built-in commands?
No, there isn't. There will probably soon be a way to wrap native redis commands with hooks, but that's still not available.
But you can use the new module notification API in 4.0.9, and register a notification handler inside your module, and in it extract the value of the key being set - then publish it.
The notification handler should look something likes this (not testing for validity):
int NotifyCallback(RedisModuleCtx *ctx, int type, const char *event,
RedisModuleString *key) {
// We only care about SET events, right?
if (!strcasecmp(event, "SET")) {
// Open the key to get the string in it. We could have used RedisModule_Call but this is faster:
RedisModuleKey *k = RedisModule_OpenKey(ctx, key, REDISMODULE_READ);
// Just to be safe...
if (k && RedisModule_KeyType(k) == REDISMODULE_KEYTYPE_STRING) {
// Get direct access to the string. Careful now!
size_t len;
char *str = RedisModule_StringDMA(ctx, k, &len, REDISMODULE_READ);
// Sadly PUBLISH is only supported with RM_Call at the moment...
// Do change what you're publishing here of course
RedisModule_Call(ctx, "PUBLISH", "cb", MY_PUBSUB_CHANNEL, str, len);
// Cleanup
RedisModule_CloseKey(k);
}
}
return REDISMODULE_OK;
}
And you can register the handler in your module init call:
RedisModule_SubscribeToKeyspaceEvents(ctx, REDISMODULE_NOTIFY_STRING, NotifyCallback);

How to provide PIN to access smartcard programmatically?

I'm using certificates to secure my communications between client and server (no code, just endpoint configuration). Certificates are currently stored in ACOS5 smart cards. Everything works very well except that every time when WCF creates a new channel to access the server, the ACOS5 driver asks user to enter “User PIN”. Unfortunately, it happens quite often.
Is there any way to configure driver to cache PIN that user has already entered within current process at least for some time or how can I cache pin and provide it every time programmatically within same session?
I have found some useful in this article:
This is because in previous versions
of Windows each CSP would cache the
PIN you entered, but Windows 7
actually converts the PIN to a secure
token and caches that. Unfortunately
there’s only one global token cache
but the CSPs can’t use tokens
generated by others, so first the
smart card CSP prompts you and caches
a token, then SSL prompts you and
caches its own token (overwriting the
first one), then the smart card system
prompts you again (because its cached
token is gone).
But I can't use solution that was proposed by author. So what should I do?
This is a way we found and use from many years in our main application:
static class X509Certificate2Extension
{
public static void SetPinForPrivateKey(this X509Certificate2 certificate, string pin)
{
if (certificate == null) throw new ArgumentNullException("certificate");
var key = (RSACryptoServiceProvider)certificate.PrivateKey;
var providerHandle = IntPtr.Zero;
var pinBuffer = Encoding.ASCII.GetBytes(pin);
// provider handle is implicitly released when the certificate handle is released.
SafeNativeMethods.Execute(() => SafeNativeMethods.CryptAcquireContext(ref providerHandle,
key.CspKeyContainerInfo.KeyContainerName,
key.CspKeyContainerInfo.ProviderName,
key.CspKeyContainerInfo.ProviderType,
SafeNativeMethods.CryptContextFlags.Silent));
SafeNativeMethods.Execute(() => SafeNativeMethods.CryptSetProvParam(providerHandle,
SafeNativeMethods.CryptParameter.KeyExchangePin,
pinBuffer, 0));
SafeNativeMethods.Execute(() => SafeNativeMethods.CertSetCertificateContextProperty(
certificate.Handle,
SafeNativeMethods.CertificateProperty.CryptoProviderHandle,
0, providerHandle));
}
}
internal static class SafeNativeMethods
{
internal enum CryptContextFlags
{
None = 0,
Silent = 0x40
}
internal enum CertificateProperty
{
None = 0,
CryptoProviderHandle = 0x1
}
internal enum CryptParameter
{
None = 0,
KeyExchangePin = 0x20
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptAcquireContext(
ref IntPtr hProv,
string containerName,
string providerName,
int providerType,
CryptContextFlags flags
);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CryptSetProvParam(
IntPtr hProv,
CryptParameter dwParam,
[In] byte[] pbData,
uint dwFlags);
[DllImport("CRYPT32.DLL", SetLastError = true)]
internal static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
CertificateProperty propertyId,
uint dwFlags,
IntPtr pvData
);
public static void Execute(Func<bool> action)
{
if (!action())
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
The full post and author is here:
http://www.infinitec.de/post/2010/11/22/Setting-the-PIN-of-a-smartcard-programmatically.aspx
Actually I have found answer on my question: the described behavior caused by bug in Advanced Card Systems CSP v1.9. After switching to Alladin eToken application works as it should.
So I can't provide PIN from code but it is remembered by CSP after entering and providing from code is not required. More good news: user sees PIN request in familiar dialog from CSP in this case.