Error performing esp-idf OTA update from AWS S3 - esp-idf

I'm trying to perform an OTA update with esp-idf by downloading firmware from an S3 bucket. I'm using the following provided snippet:
esp_http_client_config_t config = {
.url = "https://my-bucket-name-here.s3.amazonaws.com/firmware.bin",
.cert_pem = (char *)server_cert_pem_start,
.event_handler = _http_event_handler,
};
esp_err_t ret = esp_https_ota(&config);
if (ret == ESP_OK) {
esp_restart();
} else {
ESP_LOGE(TAG, "Firmware upgrade failed");
}
When put that URL in my browser or wget it, the file downloads fine. However, the download fails on the ESP32. I get the following message:
␛[0;31mE (1043) esp-tls: couldn't get hostname for :my-bucket-name-here.s3.amazonaws.com:␛[0m
␛[0;31mE (1053) esp-tls: Failed to open new connection␛[0m>
␛[0;31mE (1063) TRANS_SSL: Failed to open a new connection␛[0m
␛[0;31mE (1063) HTTP_CLIENT: Connection failed, sock < 0␛[0m
␛[0;31mE (1073) esp_https_ota: Failed to open HTTP connection: ERROR␛[0m
␛[0;31mE (1073) esp_https_ota: Failed to establish HTTP connection␛[0m
␛[0;31mE (1083) subpub: Firmware upgrade failed␛[0m
I was able to track it down to the function that throws the first error. It's thrown by resolve_host_name() in esp_tls.c here. Specifically, the error occurs in this chunk of code:
if (getaddrinfo(use_host, NULL, &hints, address_info)) {
ESP_LOGE(TAG, "couldn't get hostname for :%s:", use_host);
free(use_host);
return ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME;
}
Any clue why getaddrinfo wouldn't be able to resolve an S3 bucket address? I thought I might have used the wrong certificate, but this seems to be before the certificate is even used.

Can you log your Heap sizes before and after the request.
esp_get_free_heap_size();
esp_get_minimum_free_heap_size();
You would need probably 40K of heap available before making https/tls request.

If anyone from the future runs into this problem while trying the example from esp-idf, the problem is that xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); is called before wifi is fully set up. I have an event_handler function for wifi, and creating the task after a SYSTEM_EVENT_STA_GOT_IP event worked for me.

Related

How do I force Solana/Anchor methods to use the devnet?

In creating a simple program, I can't get Solana to use the devnet for its RPC connection. I keep getting the following error:
{
blockhash: '7TTVjRKApwAqP1SA7vZ2tQHuh6QbnToSmVUA9kc7amEY',
lastValidBlockHeight: 129662699
}
Error: failed to get recent blockhash: FetchError: request to http://localhost:8899/ failed, reason: connect ECONNREFUSED 127.0.0.1:8899
at Connection.getRecentBlockhash (/home/simeon/dev/freelance/niels_vacancies/node_modules/#solana/web3.js/lib/index.cjs.js:6584:13)
even though I have set all of my settable constants like ANCHOR_PROVIDER_URL=https://api.devnet.solana.com, or the relevant entries in my Anchor.toml file. I also explicitly specify the following:
const connection = new anchor.web3.Connection("https://api.devnet.solana.com/", {commitment: "max"});
const wallet = anchor.Wallet.local();
const provider = new anchor.Provider(
connection,
wallet,
{
commitment: "max",
preflightCommitment: "max",
skipPreflight: false
}
)
I even test console.log(await anchor.getProvider().connection.getLatestBlockhash()); to ensure that I can, in fact, get a blockhash from the devnet. What can I do to force the RPC calls to do so too?
You just have to set the Anchor.toml cluster to devnet and programs.devnet and then deploy the program using a wallet with devnet-sol. I will drop an Anchor.toml for devnet.
[features]
seeds = false
[programs.devnet]
first_program = "FPT...bd3"
[registry]
url = "https://anchor.projectserum.com"
[provider]
cluster = "devnet"
wallet = "PATH/TO/WALLET/WHO/WILL/PAY/FOR/DEPLOY.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
in this case the first_program is the program_id declared on the declare_id macro.
Then you can use ur test file totally normal with anchor.setProvider(anchor.Provider.env());
If you have already updated the anchor.toml to use devnet, and are having this issue with program.provider.connection.whatever or program.account.whatever.fetch.whatever, make sure that you have set the anchor provider BEFORE creating the program, e.g:
const provider = AnchorProvider.env();
anchor.setProvider(provider);
must come before the line
const program: Program<Whatever> = workspace.Whatever;

IOCreatePlugInInterfaceForService failed w/ kIOReturnNoResources/0xe00002be

IOCreatePlugInInterfaceForService failed w/ kIOReturnNoResources/0xe00002be
I am rewriting old FireWire based command line utility into XPCService. I need some help about an IOKit function.
Following part is to get IOCFPlugInInterface for FireWireAVCLibUnit.(almost same as original code; basic idea comes from legacy simpleAVC samplecode).
When I call IOCreatePlugInInterfaceForService() in the XPCService, it always failed returning 0xe00002be = kIOReturnNoResources in IOReturn.h.
I have confirmed no sandbox, no hardened for the XPC Service.
Original command line utility works perfectly on macOS 10.14 though, would you someone give me a hint on this topic?
CFDictionaryRef dict = CFDictionaryCreateCopy(kCFAllocatorDefault, self.dict);
kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault, dict, &serviceIterator);
if (result == KERN_SUCCESS && serviceIterator != IO_OBJECT_NULL) {
while ((service = IOIteratorNext(serviceIterator)) != IO_OBJECT_NULL) {
SInt32 score = 0;
kern_return_t result = IOCreatePlugInInterfaceForService(service,
kIOFireWireAVCLibUnitTypeID,
kIOCFPlugInInterfaceID,
&interface,
&score);
if (result != KERN_SUCCESS) continue;
// result 0xe00002be = kIOReturnNoResources in IOReturn.h
break;
}
}
Additional details
I have find IOCFPlugIn.c in opensource.apple.com. After basic verification,
- IOCreatePlugInInterfaceForService() failed to IOCFPlugIn->Start() .
(*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(interfaceType),
(LPVOID *)&interface);
<snip>
kr = (*interface)->Probe(interface, plist, service, &score);
<snip>
haveOne = (kIOReturnSuccess == (*interface)->Start(interface, plist, service));
Probe() returned kIOReturnSuccess though,
Start() failed w/ kIOReturnNoDevice = 0xe00002c0. and haveOne = false.
Finally IOCreatePlugInInterfaceForService() returned kIOReturnNoResources = 0xe00002be.
Is this related to some security feature on macOS?
MODIFIED
I have found hardened runtime with Camera access was rejected FireWireAVCLibUnit (tccd shows error).
Even if no sandbox, no hardened for the XPC Service in Xcode was checked, XPCservice is handled via sandbox. (macOS 10.14.6 + Xcode 10.3)
I would appreciate if you have an advice.
I have found the solution.
- Add NSCameraUsageDescription in Info.plist, and IOFireWireAVCUserClient will work.
- If sandboxed, com.apple.security.device.firewire is also required.
Even if capabilities-sandbox is off, tccd verify info.plist.
If “Privacy - Camera Usage Description” is not available, sandboxd reject to use IOFireWireAVCUserClient device.
Information Property List Key Reference/Cocoa Keys

zmq.error.ZMQError: Cannot assign requested address

I have the following pull - publisher ZMQ schema on an Amazon EC2 machine:
I am working with the Public IP address of my EC2 Amazon machine.
I am trying send data via ZMQ PUSH socket from the client side to ZMQ PULL socket server side, which is this:
import zmq
from zmq.log.handlers import PUBHandler
import logging
# from zmq.asyncio import Context
def main():
ctx = zmq.Context()
publisher = ctx.socket(zmq.PUB)
# publisher.bind("tcp://*:5557")
publisher.bind("tcp://54.89.25.43:5557")
handler = PUBHandler(publisher)
logger = logging.getLogger()
logger.addHandler(handler)
print("Network Manager CNVSS Broker listening")
collector = ctx.socket(zmq.PULL)
# collector.bind("tcp://*:5558")
collector.bind("tcp://54.89.25.43:5558")
while True:
message = collector.recv()
print("Publishing update %s" % message)
publisher.send(message)
if __name__ == '__main__':
main()
But when I excute this script, I get this error:
(cnvss_nm) ubuntu#ip-172-31-55-72:~/cnvss_nm$ python pull_pub-nm.py
Traceback (most recent call last):
File "pull_pub-nm.py", line 28, in <module>
main()
File "pull_pub-nm.py", line 10, in main
publisher.bind("tcp://54.89.25.43:5557")
File "zmq/backend/cython/socket.pyx", line 547, in zmq.backend.cython.socket.Socket.bind
File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc
zmq.error.ZMQError: Cannot assign requested address
(cnvss_nm) ubuntu#ip-172-31-55-72:~/cnvss_nm$
I've changed my IP-address to publisher.bind("tcp://*:5557") and collector.bind("tcp://*:5558") in the server side, and my script is running:
(cnvss_nm) ubuntu#ip-x-x-x-x:~/cnvss_nm$ python pull_pub-nm.py
Network Manager CNVSS Broker listening
But from my client-side code ( added recently ), any data is sent.
#include <zmq.hpp>
#include <zmq.h>
#include <iostream>
#include "zhelpers.hpp"
using namespace std;
int main(int argc, char *argv[])
{
zmq::context_t context(1);
/*
std::cout << "Sending message to NM Server…\n" << std::endl; */
zmq::socket_t subscriber(context, ZMQ_SUB);
subscriber.connect("tcp://localhost:5557");
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);
zmq::socket_t sender(context, ZMQ_PUSH);
sender.connect("tcp://localhost:5558");
string firstMessage = "Hola, soy el cliente 1";
while (1)
{
// Wait for next request from client
std::string string = s_recv(subscriber);
std::cout << "Received request: " << string << std::endl;
// Do some 'work'
// sleep(1);
// Send reply back to client
// zmq::message_t message(firstMessage.size() + 1);
// Cualquiera de los dos se puede
// memcpy(message.data(), firstMessage.c_str(), firstMessage.size() + 1);
// s_send(sender, "Hola soy un responder 1");
// sender.send(message);
}
}
I think that my inconvenient is on my EC2 machine network configuration or on the way of setup the IP address of the server.
When I test the clients and server locally, all it works perfectly.
Is there any possibility of performing some forwarding or NAT operation on my EC2 machine?
My clients do not reach the server.
I have the security groups rule the above mentioned ports 5557 and 5558.
How to solve this inconvenience?
I had a similar situation where I was using ZMQ on EC2 and getting "Cannot assign requested address." I was also using Elastic IP as suggested in the answer, but it did not work for me. It turned out that on EC2, the sending side (ZMQ.PUSH) needs to bind to the private IP rather than to the public, while the receiving side needs to bind to the public IP, so trying to bind the server to Elastic IP caused the error. After I changed it to bind the server ZMQ.PUSH side to Private IP and the client ZMQ.PULL to Elastic IP (on the same port), it worked.
How to solve this inconvenience?
1 )If in doubts about the EC2 addresses, first try to test the reversed .bind() / .connect(), so that the EC2-side localhost address assignments are out f the game, and your connectivity proof towards a known IP-address will not depend on the EC2-side settings.
2 )Next, given there are no details about the client-side part of the MCVE, I may have got the scenario idea incorectly, so bear with me - there are only these compatible ZeroMQ Scalable Formal Communication Archetype sockets' matches available ever since, up to API v4.2.x in 2018/Q2:
{ PUB: [ SUB,
XSUB,
None
],
PULL: [ PUSH,
None
],
...
}
3 )There is a good engineering practice not to let unhandled exceptions happen, the more, if Context()-instance may still bear the possession of IP:PORT# (b)locked resource ( sometimes even beyond the python process termination ( many incidents with my own naive and this way deadlocked experiments in my past dark history :o) )
Each step in the infrastructure setup ought be wrapped into error-handling syntax-clause, best including a finally: section, where so far created resources will occasionally get dismantled in a graceful manner in cases, when exception(s) spring out. This way your code will prevent a forever hanging orphan(s), that have just an option to reboot the platform so as to get rid of these, otherwise impossible to salvage, hostages.
Problem solved,a final summary :
The initially indicated problem ( diagnosed at .bind() / .connect() phase ) was, as depicted earlier, related to Amazon EC2 instance IP-address mapping, as the term, needed for any transport-class Endpoint setup, localhost:port#
camdebu on Nov 1, 2012 5:07 PM explained all the steps needed:Setup an Elastic IP to your EC2 isntance. You will then have a static IP address. There's no cost for the Elastic IP as long as you have it pointed to an EC2 instance.
You should then have no problem connecting to your new IP Address and port as long as your security group is setup correctly.
-Cam-
Check your Security Group Rule. Make sure you allow the port to communicate from outside the instance. (Enable All TCP and Check). [ added Yesu Jeya Bensh.P ]
The recently posted client-code but shows another issue, a mutual block, generated by a non-cooperating zmq::socket_t sender( context, ZMQ_PUSH ), which actually never sends a single message.
Given the client goes into while(1)-loop as posted above, the associated peer will inadvertently get into an unsalvageable blocked state inside the python-made main(), since :
def main():
...
collector = ctx.socket( zmq.PULL )
#ollector.bind( "tcp://*:5558" )
collector.bind( "tcp://54.89.25.43:5558" )
while True:
message = collector.recv() # THIS SLOC WILL BLOCK FOREVER HERE,
... # GIVEN <sender> NEVER SENDS...
so more care is to be taken, so as to make the flow of events robust enough, not to ever fall into this or similar unsalvageable mutual block.

InitiateShutdown fails with RPC_S_SERVER_UNAVAILABLE error for a remote computer

I'm trying to implement rebooting of a remote computer with InitiateShutdown API using the following code, but it fails with RPC_S_SERVER_UNAVAILABLE or 1722 error code:
//Process is running as administrator
//Select a remote machine to reboot:
//INFO: Tried it with and w/o two opening slashes.
LPCTSTR pServerName = L"192.168.42.105";
//Or use 127.0.0.1 if you don't have access to another machine on your network.
//This will attempt to reboot your local machine.
//In that case make sure to call shutdown /a /m \\127.0.0.1 to cancel it.
if(AdjustPrivilege(NULL, L"SeShutdownPrivilege", TRUE) &&
AdjustPrivilege(pServerName, L"SeRemoteShutdownPrivilege", TRUE))
{
int nErrorCode = ::InitiateShutdown(pServerName, NULL, 30,
SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_RESTART, 0);
//Receive nErrorCode == 1722, or RPC_S_SERVER_UNAVAILABLE
}
BOOL AdjustPrivilege(LPCTSTR pStrMachine, LPCTSTR pPrivilegeName, BOOL bEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL bRes = FALSE;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
if(LookupPrivilegeValue(pStrMachine, pPrivilegeName, &tkp.Privileges[0].Luid))
{
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
bRes = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
int nOSError = GetLastError();
if(bRes)
{
if(nOSError != ERROR_SUCCESS)
bRes = FALSE;
}
}
CloseHandle(hToken);
return bRes;
}
So to prepare for this code to run I do the following on this computer, which is Windows 7 Pro (as I would do for the Microsoft's shutdown tool):
Run the following "as administrator" to allow SMB access to the logged in user D1 on the 192.168.42.105 computer (per this answer):
NET USE \\192.168.42.105\IPC$ 1234 /USER:D1
Run the process with my code above "as administrator".
And then do the following on remote computer, or 192.168.42.105, that has Windows 7 Pro (per answer here with most upvotes):
Control Panel, Network and Sharing Center, Change Advanced Sharing settings
"Private" enable "Turn on File and Printer sharing"
Set the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
LocalAccountTokenFilterPolicy=dword:1
RUN secpol.msc, then go to Local Security Policy, Security Settings, Local Policies, User Rights Assignment. Add "Everyone" to "Force shutdown from a remote system". (Just remember to remove it after you're done testing!)
Note that the following shutdown command seems to work just fine to reboot the remote computer:
shutdown /r /m \\192.168.42.105 /t 30
What am I missing with my code?
EDIT:
OK. I will admit that I was merely interested in why InitiateShutdown doesn't seem to "want" to work with a remote server connection, while InitiateSystemShutdownEx or InitiateSystemShutdown had no issues at all. (Unfortunately the latter two did not have the dwShutdownFlags parameter, which I needed to pass the SHUTDOWN_INSTALL_UPDATES flag to, which caused my persistence...)
At this point I had no other way of finding out than dusting out a copy of WinDbg... I'm still trying to dig into it, but so far this is what I found...
(A) It turns out that InitiateSystemShutdownEx internally uses a totally different RPC call. W/o too many details, it initiates RPC binding with RpcStringBindingComposeW using the following parameters:
ObjUuid = NULL
ProtSeq = ncacn_np
NetworkAddr = \\192.168.42.105
EndPoint = \\PIPE\\InitShutdown
Options = NULL
or the following binding string:
ncacn_np:\\\\192.168.42.105[\\PIPE\\InitShutdown]
(B) While InitiateShutdown on the other hand uses the following binding parameters:
ObjUuid = 765294ba-60bc-48b8-92e9-89fd77769d91
ProtSeq = ncacn_ip_tcp
NetworkAddr = 192.168.42.105
EndPoint = NULL
Options = NULL
which it later translates into the following binding string:
ncacn_np:\\\\192.168.42.105[\\PIPE\\lsarpc]
that it uses to obtain the RPC handle that it passes to WsdrInitiateShutdown (that seems to have its own specification):
So as you see, the InitiateShutdown call is technically treated as Unknown RPC service (for the UUID {765294ba-60bc-48b8-92e9-89fd77769d91}), which later causes a whole bunch of credential checks between the server and the client:
which, honestly, I'm not sure I want to step into with a low-level debugger :)
At this stage I will say that I am not very well versed on "Local Security Authority" interface (or the \PIPE\lsarpc named pipe configuration.) So if anyone knows what configuration is missing on the server side to allow this RPC call to go through, I would appreciate if you could post your take on it?

Problems with map container

Introduction
I'm trying to create a port-forwarding sample with tcp connections, so I need map client identification with his socket. When the client requests port-forwarding, I have to know who owns the sockets.
To do that, I created the following code:
std::map<std::string, tcp::socket> box_map;
std::map<std::string, tcp::socket>::iterator it;
it = box_map.find(id);
if (it != box_map.end())
return;
else{
box_map.insert(std::pair<std::string, tcp::socket>(id,s));
return;
}
Problem
But I got the following error:
error: use of deleted function ‘boost::asio::basic_stream_socket<boost::asio::ip::tcp>::basic_stream_socket(const boost::asio::basic_stream_socket<boost::asio::ip::tcp>&)’
tcp::socket is not copy constructible. So you'd have to construct the new pair in-place by moving your socket using emplace:
box_map.emplace(id, std::move(s));
Alternatively, you could just still use insert and just move into the pair you're constructing:
box_map.insert(std::make_pair(id, std::move(s)));

Resources