I'm using an mbed enabled board for development, I need to run an Ethernet application on it.
I tried to create a connection by using the following code:
network = new EthernetInterface();
network->connect();
// Show the network address
const char *ip = network->get_ip_address();
printf("IP address is: %s\n", ip ? ip : "No IP");
Normally it should work, But it fails in the LWIPInteraface class's bringup API at osSemaphoreAcquire, returning a timeout error.
if (!netif_is_link_up(&netif)) {
if (blocking){
if (osSemaphoreAcquire(linked, 15000) != osOK){
if (ppp){
(void) ppp_lwip_disconnect(hw);
}
return NSAPI_ERROR_NO_CONNECTION;
}
}
}
Any reason why I might be getting a timeout from osSemaphoreAcquire?
I tried increasing the timeout too but in vain.
If someone could help me with it, would be appreciated.
Thanks in advance.
Related
Problem
Espressif's ESP-32 (specifically the ESP-WROOM-32 in this case) appears on a network with the default hostname "Espressif". I don't want to use this hostname, so I've opted to change it as follows:
// Initialize the TCP/IP adapter (launches handler task)
tcpip_adapter_init();
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
return err;
}
Of course, this isn't working. I get back the following error: ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY.
Attempted Solutions
To solve this, I look to see if the TCP/IP adapter will post some kind of event when it is finished initializing. That way I can register a handler to set the hostname. The Espressif WiFi Driver Guide here indicates a task is launched - so there is probably an event right:
"The main task calls tcpip_adapter_init() to create an LwIP core task and initialize LwIP-related work."
Well I cannot find any such events. Neither the API documentation nor the actual file itself (tcpip_adapter.h) have it. I checked the header file for events, and none seem to exist solely for the purpose of indicating that the TCP/IP adapter has finished starting:
/** IP event declarations */
typedef enum {
IP_EVENT_STA_GOT_IP, /*!< ESP32 station got IP from connected AP */
IP_EVENT_STA_LOST_IP, /*!< ESP32 station lost IP and the IP is reset to 0 */
IP_EVENT_AP_STAIPASSIGNED, /*!< ESP32 soft-AP assign an IP to a connected station */
IP_EVENT_GOT_IP6, /*!< ESP32 station or ap or ethernet interface v6IP addr is preferred */
IP_EVENT_ETH_GOT_IP, /*!< ESP32 ethernet got IP from connected AP */
} ip_event_t;
Possible Lead
I have noticed that in Espressif's WiFi guide they indicate that the event SYSTEM_EVENT_STA_START (which indicates that a station has started), will:
Upon receiving this event, the event task will initialize the LwIP network interface (netif).
If I place the call after a handler receives this event, I no longer get the error:
// After the event WIFI_EVENT_STA_START
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) {
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
fprintf(stderr, "Err: %s", esp_err_to_name(err));
}
...
}
However, the hostname still hasn't changed. Therefore I find myself a bit stuck. How can I actually change the hostname? I've found little to no results from searching this problem. However, the esp32 is a popular module and I'm sure many other people will find themselves facing the same problem.
Turns out I was doing it correctly. It was my router that had failed to refresh the hostname adequately. For consistency I will restate what I did to solve this problem:
The Espressif WiFi Guide indicates that the event SYSTEM_EVENT_STA_START is generated once esp_wifi_start() returns successfully.
The generation of this event also means that the event task will initialize the LwIP network interface (netif). Since we know that the TCP/IP adapter will surely have been initialized at this point, we can invoke the hostname change function. Here is an example of a handler that does that, taken right from their example:
void wifi_event_handler (void *handler_arg, esp_event_base_t base, int32_t id,
void *event_data) {
esp_err_t err;
// If esp_wifi_start() returned ESP_OK and WiFi mode is in station mode
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) {
const char *name;
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
fprintf(stderr, "Err: %s", esp_err_to_name(err));
} else {
if ((err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &name)) != ESP_OK) {
fprintf(stderr, "Err Get Hostname: %s\n", esp_err_to_name(err));
} else {
printf("Hostname: %s\n", (name == NULL ? "<None>" : name));
}
}
...
}
...
}
In this example I get the hostname after setting it, and print it to stdout. You can validate it if you are running the monitor for the ESP32. The hostname set will be the one visible from the router page.
I got an error on my arduino when I send a UDP-package any ip.
There 2 problems when I try to send a packet to _targetIp:
When called from loop() then udpSender.endPacket() freeze forever (on second call, first call was fine)
When called from setup() then udpSender.beginPacket(...) returns 0
Code:
IPAddress _targetIp(192, 168, 59, 250);
int _sendPort = 4321;
EthernetUDP _udpSender;
(...)
void sendUpd(int pinIndex, int value)
{
// if I wrote something like this:
// udpSender.beginPacket(_udpSender.remoteIP(), _sendPort)
// then is all fine
if (_udpSender.beginPacket(_targetIp, _sendPort) != 1)
{
Serial.println("socket error!");
return;
}
_udpSender.write(pinIndex);
_udpSender.write("=");
_udpSender.write(value);
int sendState = _udpSender.endPacket(); // hang forever when called from "loop()"
if ( sendState != 1 )
{
// enters with 0 as "sendState" when called from "setup()"
Serial.print("send error: ");
Serial.println( sendState );
}
}
Can anybody explain that for me?
Founded solutions:
Not the call _updSender.endPacket() freezes. The code to read a specific digital in (digitalRead(52)) causes the strange reaction.
I dont know how, but the arduino check if the host alive. If the host not reachable, the _udpSender.endPacket() returns 0.
Explantation:
Resolving the IP to an MAC adress fails. So the error does not came from UDP (layer 4 OSI). The error happend in data-link-layer (=2) and explains point 2.
I am working on a game written in C using SDL. Given that it already uses SDL, SDL_image, and SDL_ttf, I decided to add SDL_mixer and SDL_net to my engine. Getting SDL_mixer set up and working was very easy, but I am having a lot of trouble with SDL_net.
To test I created a very simple application with the following rules:
Run without arguments act as a TCP server on port 9999
Run with an argument try to connect to the server at the given IP address on port 9999
Here are some of the key lines of the program (I'm not going to post my whole event-driven SDL engine because its too long):
char *host = NULL;
if (argc > 1) host = argv[1];
and...
IPaddress ip;
TCPsocket server = NULL;
TCPsocket conn = NULL;
if (host) { /* client mode */
if (SDLNet_ResolveHost(&ip,host,port) < 0)
return NULL; //this is actually inside an engine method
if (!(conn = SDLNet_TCP_Open(&ip)))
return NULL;
} else { /* server mode */
if (SDLNet_ResolveHost(&ip,NULL,port) < 0)
return NULL;
if (!(server = SDLNet_TCP_Open(&ip)))
return NULL;
}
and... inside the event loop
if (server) {
if (!conn)
conn = SDLNet_TCP_Accept(server);
}
if (conn) {
void *buf = malloc(size); //server, conn, size are actually members of a weird struct
while (SDLNet_TCP_Recv(conn,buf,size))
onReceive(buf); //my engine uses a callback system to handle things
free(buf);
}
The program seems to start up just fine. However for some reason when I run it in client mode trying to connect to my home computer (which I have on a different IP) from my laptop I find that the call to SDLNet_TCP_Open blocks the program for awhile (5-10 seconds) then returns NULL. Can anybody see what I did wrong? Should I post more of the code? Let me know.
I am using QMI SDK to start data session for the Sierra Wireless card MC7354 and Telus Sim Card. For now I can detect the device and the sim card like getting device info and IMSI number; however, I got some trouble with starting the data session. I follow the instructions in QMI SDK Documents and do the following code:
//set the default profile
ULONG rc3 = SetDefaultProfile(0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
fprintf(stderr, "SetProfile - Return Code: %lu\n", rc3);
//start the session
ULONG technology = 1;
ULONG profile_idx = 1;
struct ssdatasession_params session;
session.action = 1;
session.pTechnology = &technology;
session.pProfileId3GPP = &profile_idx;
session.pProfileId3GPP2 = NULL;
session.ipfamily = 4;
ULONG rc4 = SLQSStartStopDataSession(&session);
fprintf(stderr, "Start Session - Return Code: %lu\n",rc4);
SetDefaultProfile is working fine because it returns me the success code, but for the SLQSStartStopDataSession method, it always gives me the return code "1026", which means
Requested operation would have no effect
Does anyone know where I make mistakes and how should I modify the code? What does this return code mean?
A "No Effect" error in WDS Start Network (the underlying command sent when you use SLQSStartStopDataSession()) actually means that the device is already connected. You likely have configured an automatic connection setup in the modem.
I'm facing a problem in implementing multi-homing in SCTP as the server side. The server has 2 IPs it is listening to.
I'm almost there, but there are 2 problems:
First IP returns the INIT-ACK with 2 different IPs inside the header as it should but the other IP return twice the same IP in the INIT-ACK header.
Seems like I’m not supporting 100 % in multi-homing, for example, if one of the links is down I don’t see a fail over.
So I don’t know if except the setsockopt with the option SCTP_SOCKOPT_BINDX_ADD I need anything else (maybe SCTP_PRIMARY_ADDR?) or what is wrong in my implementation.
Following is the code, I enter this code twice, first time I do bind and then save the socket and the first address, second time again bind (for the second IP) and then running setsockopt for both of the addresses and sockets.
bind(socket, &sock_addr.addr.sock_addr, sock_addr_len);
if(SHARED.num_used_entries_in_sockaddr_array == 0)
{
SHARED.saved_socket = socket;
SHARED.sockaddr_array[1] = sock_addr.addr.sock_addr;
}
else
{
SHARED.sockaddr_array[0] = sock_addr.addr.sock_addr;
}
if(SHARED.num_used_entries_in_sockaddr_array > 0)
{
sock_rc = setsockopt(SHARED.saved_socket,
IPPROTO_SCTP,
SCTP_SOCKOPT_BINDX_ADD,
(char*)SHARED.sockaddr_array,
sizeof(SCKOS_SOCK_ADDR));
sock_rc = setsockopt(socket,
IPPROTO_SCTP,
SCTP_SOCKOPT_BINDX_ADD,
(char*)SHARED.sockaddr_array,
sizeof(SCKOS_SOCK_ADDR));
}
SHARED.num_used_entries_in_sockaddr_array++;
Thanks!!!
SCTP_SOCKOPT_BINDX_ADD is ok for multi-homing. your codes have some unused lines.
if(SHARED.num_used_entries_in_sockaddr_array == 0)
{
bind(socket, &sock_addr.addr.sock_addr, sock_addr_len);
}
else
{
sock_rc = setsockopt(socket,
IPPROTO_SCTP,
SCTP_SOCKOPT_BINDX_ADD,
(char*)sock_addr.addr.sock_addr,
sizeof(SCKOS_SOCK_ADDR));
}enter code here
You can refer to linux sctp implemantation. Did you see heartbeat on all paths? Which box you test on?
thanks for the answer, in the end I used sctp_bindx which is much easier to implement