TCP Retransmition - tcp

I am trying to do TCP connection between two stm32 device. Firstly everything is perfect between the line we see on the wireshark.When the TCP client reset and try to send new data, wireshark shows me Retransmittion TCP message but when I debug the server side, server side get the message and send echo message after client receive this echo message.
Why the retransmition message shows, althoug I get and send message to other side ?
FULL client code: https://paste.ubuntu.com/p/VJHzgv29FM/
FULL server code : https://paste.ubuntu.com/p/Wm9gvkSfF7/
/**
* #brief Initializes the tcp echo server
* #param None
* #retval None
*/
void tcp_echoserver_init(void)
{
/* create new tcp pcb */
tcp_echoserver_pcb = tcp_new();
if (tcp_echoserver_pcb != NULL)
{
err_t err;
/* bind echo_pcb to port 7 (ECHO protocol) */
err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);
if (err == ERR_OK)
{
/* start tcp listening for echo_pcb */
tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);
/* initialize LwIP tcp_accept callback function */
tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
}
else
{
/* deallocate the pcb */
memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
}
}
}
Client:
/**
* #brief Connects to the TCP echo server
* #param None
* #retval None
*/
void tcp_echoclient_connect(void)
{
ip_addr_t DestIPaddr;
/* create new tcp pcb */
echoclient_pcb = tcp_new();
if (echoclient_pcb != NULL)
{
IP4_ADDR(&DestIPaddr, (uint8_t)192, (uint8_t)168, (uint8_t)1, (uint8_t)40);
/* connect to destination address/port */
tcp_connect(echoclient_pcb,&DestIPaddr,7,tcp_echoclient_connected);
}
else
{
SerialPrint("not null");
memp_free(MEMP_TCP_PCB, echoclient_pcb);
}
}

When using wireshark to analyze network stream, here is a doc from wireshark that can help you understand what these words means.
We can see the following thing:
TCP Retransmission
Set when all of the following are true:
This is not a keepalive packet.
In the forward direction, the segment length is greater than zero or the SYN or FIN flag is set.
The next expected sequence number is greater than the current sequence number.
For your circumstance, the problem is that the segment length is greater than zero or the SYN or FIN flag is set. This is caused by your reset, so this doesn't mean that your TCP connection causes retransmission.

Related

Please tell me how to solve lwip tcp server error

I made this Source code to implement lwip tcp server
If you try to remove the st-link wire and do it without debugging, the server itself doesn't work.
I try to find a way, but I don't know where the problem is.
If the LED on the board blinks, it means it's down.
Is there a problem with why the server is not working?
If you turn it to debugging, you receive it without any problems, generate a message, and then send it.
Then isn't there a problem with the Source code?
If the connection itself is not working when there is no debugging, I don't think the server is created
But if it's a circuit problem, I think it's weird to be a server when you debug it
I don't know where to look.
When debugging, the client sent and received properly when it connected to the client from hercules or Raspberry Pi
void Tcp_Task(void const * argument)
{
/* USER CODE BEGIN Tcp_Task */
struct netconn *conn, *newconn;
err_t err, accept_err;
struct netbuf *buf;
void *data;
u16_t len;
MX_LWIP_Init();
LWIP_UNUSED_ARG(argument);
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL)
{
// netconn_bind(conn, NULL, port 번호)
err = netconn_bind(conn, NULL, 5001);
if (err == ERR_OK)
{
netconn_listen(conn);
while (1)
{
accept_err = netconn_accept(conn, &newconn);
if (accept_err == ERR_OK)
{
while (netconn_recv(newconn, &buf) == ERR_OK)
{
do
{
netbuf_data(buf, &data, &len);
memcpy(receivemsg, data, len);
transmitmsg = procPacket();
msg_len = getsendPackSize();
netconn_write(newconn, transmitmsg, msg_len, NETCONN_COPY);
}
while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
netconn_close(newconn);
netconn_delete(newconn);
}
osDelay(100);
}
}
else
{
netconn_delete(newconn);
}
}
/* Infinite loop */
for(;;)
{
osDelay(100);
}
/* USER CODE END Tcp_Task */
}
lwip tcp server Source code site
[https://blog.naver.com/eziya76/221867311729](lwip tcp server)
I don't think I can implement the server if I turn the board off and on or without debugging, but I don't know where to find the problem
Please let me know if the Source code is the problem, and if the other place is the problem, please tell me how to find it
I'm writing this using a translator, so please understand

Async mosquitto client trying to re-connect with mosquitto broker

Trying to implement an asynchronous client based in mosquitto MQTT broker, running forever in the background. My purpose is create a client able to connect / reconnect to broker in case the broker becomes offline at some time. I expected all connection / reconnection logic was managed by mosquitto callbacks (event-driven). However, this code doesn't try to connect to broker in case you try to run the client when the broker is stopped (offline) at initial time:
struct mosquitto *broker;
char ip[INET_ADDRSTRLEN]; // broker ip address
int port; // 1883
int keepalive; // 60
bool running = true;
int main(void)
{
mosquitto_lib_init();
broker = mosquitto_new(NULL, true, NULL);
mosquitto_connect_callback_set(broker, on_connect_callback);
mosquitto_disconnect_callback_set(broker, on_disconnect_callback);
mosquitto_message_callback_set(broker, on_message_callback);
mosquitto_connect_async(broker, ip, port, keepalive);
mosquitto_loop_start(broker);
while(running) {
pause();
}
}
After some testing, replaced
mosquitto_connect_async(broker, ip, port, keepalive);
by a while loop polling for the first success returned by mosquitto_connect_async function:
bool connected_to_broker = false;
while (!connected_to_broker) {
rc = mosquitto_connect_async(broker, ip, port, keepalive);
if (rc == MOSQ_ERR_SUCCESS) {
connected_to_broker = true;
} else {
sleep(retry_timeout);
}
}
After the while loop, it seems all the source code can be based on mosquitto callbacks.
Is this the expected way to manage this situation? Or should be managed in a different way? Thanks!
You don't have to make multiple connection attempts. Your problem is that the first attempt fails for the same reason but does not yet fire any callbacks because the communication thread is not yet started.
If you check the return value of mosquitto_connect_async you will see it is MOSQ_ERR_ERRNO with errno being set to ECONNREFUSED (111).
If mosquitto_loop_start is called before your first connection attempt, the disconnect callback should be fired - also with rc == MOSQ_ERR_ERRNO and errno == ECONNREFUSED

How do I get the remote address of a client in servlet?

Is there any way that I could get the original IP address of the client coming to the server?
I can use request.getRemoteAddr(), but I always seem to get the IP of the proxy or the web server.
I would want to know the IP address that the client is using to connect to me. Is there anyway that I could get it?
try this:
public static String getClientIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
Why don't use a more elegant solution like this?
private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");
public static String getClientIpAddr(HttpServletRequest request) {
return IP_HEADERS.stream()
.map(request::getHeader)
.filter(Objects::nonNull)
.filter(ip -> !ip.isEmpty() && !ip.equalsIgnoreCase("unknown"))
.findFirst()
.orElseGet(request::getRemoteAddr);
}
Deduplicate your code!
request.getRemoteAddr() is the way. It appears your proxy changes the source IP. When some proxies do that they add the original IP in some custom http header. Use request.getHeaderNames() and request.getHeaders(name) and print all of them to see if there isn't anything of interest. Like X-CLIENT-IP (made that one up, but they look like this)
As this is usually a deployment concern, rather than an application concern, another approach would be to configure the application container appropriately. Once configured, the container takes care of inspecting the appropriate header and your application continues to use request.getRemoteAddr().
For example, in Tomcat you can use the Remote IP Valve. I would assume most application servers have similar functionality.
The container could also take care of understanding if your front-end load balancer is terminating SSL connections, forwarding the request to the app server over HTTP. This is important when your application needs to generate URLs to itself.
The best solution I've ever used
public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
You cannot do this in a meaningful way.
The proxy may or may not add a proxied-for header, but in many cases this will be an internal only address anyway, so it will be meaningless to you. Most proxies at the edge of an organization are configured to reveal as little as possible about the internals of the network anyway.
What are you intending to use this information for?
"x-forwarded-for" request header contains the original client IP if using a proxy or a load balancer. But I think not all proxies/lb adds this header.
Here some java code to parse the header:
http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html
If this header is not present then I would proceed as #Bozho suggests
String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null) {
ipAddress = request.getHeader("X_FORWARDED_FOR");
if (ipAddress == null){
ipAddress = request.getRemoteAddr();
}
}
Why I think we should try to get IP from header 'X-Forwarded-For' first? If you get from request.getRemoteAddr(), it could be client's real ip or last proxy's ip which forwards the request. Thus we can't tell which condition it belongs to. However, if 'X-Forwarded-For' is set into the header, client ip is bound to be the left-most part of what you get from it.
/**
* Try to get real ip from request:
* <ul>
* <li>try X-Forwarded-For</li>
* <li>try remote address</li>
* </ul>
*
* #param request request
* #return real ip or ""
*/
private String tryGetRealIp(HttpServletRequest request) {
// X-Forwarded-For: <client>, <proxy1>, <proxy2>
// If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
// This means, the right-most IP address is the IP address of the most recent proxy and
// the left-most IP address is the IP address of the originating client.
String forwards = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotBlank(forwards)) {
// The left-most IP must be client ip
String ip = StringUtils.substringBefore(forwards, ",");
return ip;
} else if (StringUtils.isNotBlank(request.getRemoteAddr())) {
// this could be real client ip or last proxy ip which forwards the request
return request.getRemoteAddr();
}
return "";
}
request.getHeader("True-Client-IP")
it will return the client IP address
InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();

Tinyos reception after second reply doesn't work

I'm in trouble with my nesC code. In my code I send a first packet using AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)).
After that, when a message is received in function event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){ a reply is generated and sent successfully, but the other nodes are not able to receive the reply. In particular I have to process a RREP reply, following the basics of DSR protocol.
This is my code:
implementation{
/**********************Variables used*****************************/
short phase = 0;
message_t packet;
bool locked;
event void Boot.booted(){
dbg("Boot", "Node %hhu booted\n", TOS_NODE_ID);
call AMControl.start();
}
[cut]
event void MilliTimer.fired(){
/*This contains the discovery message*/
rd_message *rreq = NULL;
if (phase == 0){
//Route discovery phase
rreq = (rd_message *) call Packet.getPayload(&packet, (int) NULL);
if(call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) == SUCCESS){
//locked = TRUE;
}
return;
}
}
event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){
rd_message *received_mex = NULL;
rd_message *reply_mex = NULL;
int i,j;
received_mex = (rd_message*) payload; //cast to rd_message
if (received_mex->type == RREQ){
reply_mex = (rd_message*) call Packet.getPayload(&packet, (int) NULL); //reply packet is created.
if (received_mex->sender_id == TOS_NODE_ID){
//The original sender received its RREQ. Stopping the forward procedure
return bufPtr; //FIXME: see if it's correct to return null here
}
//RREQ message case 1: I am not the receiver_id
if (received_mex->receiver_id != TOS_NODE_ID){
}
else if (received_mex->receiver_id == TOS_NODE_ID){
//I am the receiver of the RREQ message. I can now reply with a RREP
}
if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) == SUCCESS) {
dbg("dsr", "packet sent\n");
//locked = TRUE;
}
else{
dbg("dsr", "failed to send reply packet.\n");
}
}
else if (received_mex->type == RREP){
//DO SOMETHING WITH CHE NEW RECEIVED MESSAGE HERE
}
return bufPtr;
}
event void AMSend.sendDone(message_t* bufPtr, error_t error) {
if (&packet == bufPtr) {
//locked = FALSE;
}
}
I removed all the logic from the code to focus on the message exchange calls. I hope that someone can help me... thanks.
TinyOS follows almost everywhere a ownership discipline: at any point in time, every
"memory object" - a piece of memory, typically a whole variable or a single array element - should be owned by a single module. A command like send is said to pass ownership of its msg argument from caller to callee.
The main problem of your code is that in the Receive.receive event you are using the packet variable in two ways:
as outgoing packet by calling call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))
as buffer for the next incoming packet by executing return bufPtr;
the result of this code is unpredictable (since receiving a packet will corrupt the outgoing packet). To solve your problem, you should use a Pool<message_t> component. The typical pseudocode for a program like yours is like:
receive (m):
if I don't need to process this message, return m
if my free packet list is empty, return m
else
process/forward m
return entry from free packet list
This is a rough implementation of a module that uses Pool<message_t> as list of free packets to manage communication:
module Foo
{
/* this is our free packet list */
uses interface Pool<message_t>;
uses interface Receive;
uses interface AMSend;
}
implementation
{
event void MilliTimer.fired()
{
message_t *packet;
/* get a free packet */
packet = Pool.get();
if (packet)
{
/* code to send the packet */
}
}
event void AMSend.sendDone(message_t *msg, error_t error)
{
/* the send function ended, put back the packet in the free packet pool */
/* check here if msg was taken from Pool */
call Pool.put(msg);
}
event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
{
if (!haveToProcess(msg))
return msg; // don't have to process this message
if (Pool.empty())
return msg; // memory exahusted;
/* ... */
/* code that processes the packet */
call AMSend.send(AM_BROADCAST_ADDR, msg, sizeof(rd_message));
/* return a free message_t* as buffer to store the next received packet */
return Pool.get();
}
}
If you don't like Pool, you can use a message_t array as circular buffer. Take a look at the BaseStation code for a hint on how to do so.
For more details, I suggest you to read the TinyOS programming book, especially section 3.5.1.
As for your comment:
return bufPtr; //FIXME: see if it's correct to return null here
you can never return NULL in a receive event, since TinyOS needs always a buffer to store incoming packets.

Scan for available Wi-Fi networks on BlackBerry

Is there any RIM API available which will help to get the list of available network service or only Wi-Fi networks for a device and set selected network access point for any network communications?
Is it possible for my application to disable the mobile networks like GPRS, WAP, etc.?
Example:
When the application is started it should scan for Wi-Fi connections, even if there are no previous Wi-Fi network access points set on the device, and list the available Wi-Fi connections. Then the user will select the appropriate Wi-Fi connection to connect for any network communication. Outside the application any Internet communication, like the browser or any other application, should be done through the same selected Wi-Fi connection.
The scanning for Wi-Fi and setting the connection is almost similar to BlackBerry Wi-Fi Setup.
I am looking to do this for BlackBerry OS 4.5, 4.7 and 5.0.
Update
The thing is I'm looking for Wi-Fi scanning through application. It's like through the application I am able to scan available Wi-Fi access points or hotspots and set one of access point by selecting it to device, then connect to it for communication.
Basically it's like, how do we set the Wi-Fi connection in "Manage connetion" of BlackBerry? I have to do a similar thing through the applicaiton.
From some BlackBerry forums I got to know there is package in OS v5.0, that is, a net.rim.device.api.wlan.hotspot package to get the Wi-Fi hotspots. But after a long search I didn't find any sample example or much explanation on it. As I am trying to implement by looking into its API documentation, but I did not succeded.
If you have any idea related to this or any sample code it will be very helpful.
Well, to scan for all available networks for the application you can use the NetworkDiagnostic tool from RIM.
Anther piece of code to scan for your phone connectivity and get the best connection string can be found in How to reliably establish a network connection on any BlackBerry device,
/**
* Determines what connection type to use and returns the necessary string to use it.
* #return A string with the connection info
*/
private static String getConnectionString()
{
// This code is based on the connection code developed by Mike Nelson of AccelGolf.
// http://blog.accelgolf.com/2009/05/22/blackberry-cross-carrier-and-cross-network-http-connection
String connectionString = null;
// Simulator behavior is controlled by the USE_MDS_IN_SIMULATOR variable.
if (DeviceInfo.isSimulator())
{
if (UploaderThread.USE_MDS_IN_SIMULATOR)
{
logMessage("Device is a simulator and USE_MDS_IN_SIMULATOR is true");
connectionString = ";deviceside=false";
}
else
{
logMessage("Device is a simulator and USE_MDS_IN_SIMULATOR is false");
connectionString = ";deviceside=true";
}
}
// Wi-Fi is the preferred transmission method.
else if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
{
logMessage("Device is connected via Wifi.");
connectionString = ";interface=wifi";
}
// Is the carrier network the only way to connect?
else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT)
{
logMessage("Carrier coverage.");
String carrierUid = getCarrierBIBSUid();
if (carrierUid == null)
{
// Has carrier coverage, but not BIBS. So use the carrier's TCP network
logMessage("No Uid");
connectionString = ";deviceside=true";
}
else
{
// otherwise, use the Uid to construct a valid carrier BIBS request
logMessage("uid is: " + carrierUid);
connectionString = ";deviceside=false;connectionUID="+carrierUid + ";ConnectionType=mds-public";
}
}
// Check for an MDS connection instead (BlackBerry Enterprise Server).
else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS)
{
logMessage("MDS coverage found");
connectionString = ";deviceside=false";
}
// If there is no connection available abort to avoid bugging the user unnecssarily.
else if (CoverageInfo.getCoverageStatus() == CoverageInfo.COVERAGE_NONE)
{
logMessage("There is no available connection.");
}
// In theory, all bases are covered so this shouldn't be reachable.
else
{
logMessage("no other options found, assuming device.");
connectionString = ";deviceside=true";
}
return connectionString;
}
/**
* Looks through the phone's service book for a carrier provided BIBS network
* #return The uid used to connect to that network.
*/
private static String getCarrierBIBSUid()
{
ServiceRecord[] records = ServiceBook.getSB().getRecords();
int currentRecord;
for (currentRecord = 0; currentRecord < records.length; currentRecord++)
{
if (records[currentRecord].getCid().toLowerCase().equals("ippp"))
{
if (records[currentRecord].getName().toLowerCase().indexOf("bibs") >= 0)
{
return records[currentRecord].getUid();
}
}
}
return null;
}

Resources