I tried to do a 3 or 4 tcp server on my STM32F107. I'm using freeRTOS and LwIP (and the CubeMX + ST HAL library).
I create a task tcp_server, and inside the task, I create 3 netconn structure each with different tcp port.
Callback:
void socket_callback(struct netconn * conn, enum netconn_evt evt, u16_t len)
{
queue_event_t msg;
if (evt == NETCONN_EVT_RCVPLUS)
{
msg.cmd = MSG_TEST;
if (conn == user_conn.conn_modbus)
msg.cmd = MSG_MODBUS;
else if (conn == user_conn.conn_modbus_listen)
msg.cmd = MSG_MODBUS_LISTEN;
else if (conn == user_conn.conn_rs232)
msg.cmd = MSG_RS232;
else if (conn == user_conn.conn_rs232_listen)
msg.cmd = MSG_RS232_LISTEN;
else if (conn == user_conn.conn_rs485)
msg.cmd = MSG_RS485;
else if (conn == user_conn.conn_rs485_listen)
msg.cmd = MSG_RS485_LISTEN;
xQueueSend(user_conn.evtQueue, &msg, 1000);
}
}
Server creation :
static struct netconn * createServer(int port)
{
struct netconn * conn;
err_t err;
conn = netconn_new_with_callback(NETCONN_TCP, socket_callback);
if (conn == NULL)
{
char *msg = "Cannot create netconn\n\r";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
return NULL;
}
err = netconn_bind(conn, NULL, port);
if (err != ERR_OK)
{
char *msg = "Error in Binding \n\r";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
print_error(err);
netconn_delete(conn);
return NULL;
}
err = netconn_listen(conn);
if (err != ERR_OK)
{
char *msg = "Error in listenning \n\r";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
print_error(err);
netconn_delete(conn);
return NULL;
}
return conn;
}
Thread :
static void servertcp_thread()
{
queue_event_t evt;
user_conn.evtQueue = xQueueCreate(10, sizeof (queue_event_t));
user_conn.conn_modbus_listen = createServer(502);
user_conn.conn_rs232_listen = createServer(10001);
user_conn.conn_rs485_listen = createServer(50001);
while(1)
{
waitServer(&user_conn, &evt);
send_rs232(&user_conn);
send_rs485(&user_conn);
if((user_conn.conn_modbus_listen != NULL) && (evt.cmd == MSG_MODBUS_LISTEN))
processModbusListen(&user_conn);
if((user_conn.conn_rs232_listen != NULL) && (evt.cmd == MSG_RS232_LISTEN))
processRS232Listen(&user_conn);
if((user_conn.conn_rs485_listen != NULL) && (evt.cmd == MSG_RS485_LISTEN))
processRS485Listen(&user_conn);
if((user_conn.conn_modbus != NULL) && (evt.cmd == MSG_MODBUS))
modbus_tcp_server(&user_conn);
if((user_conn.conn_rs232 != NULL) && (evt.cmd == MSG_RS232))
rs232_tcp_server(&user_conn);
if((user_conn.conn_rs485 != NULL) && (evt.cmd == MSG_RS485))
rs485_tcp_server(&user_conn);
}
}
The creation is successful (netconn_new_with_callback / netconn_bind and netconn_listen with no error).
When I tried to connect to 1 tcp port, it is accepted and everything is ok.
But when I tried to connect to a second port while the first connexion is still alive, the callback is called, but the netconn_accept(conn, &newconn); failed and report ERR_ABRT and I don't know why.
The 3 function (processModbusListen, processRS232Listen and processRS485Listen) are coded following the same prototype:
static int processXXXListen(user_conn_t * user_data)
{
struct netconn *newconn;
err_t error_accept;
error_accept = netconn_accept(user_data->conn_XXX_listen, &newconn);
if (error_accept == ERR_OK)
{
if (user_data->conn_rs485)
{
// Close unwanted connection
netconn_close(newconn);
netconn_delete(newconn);
char *msg = "Error XXX Connection during establishement\n\r";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
}
else
{
// connection established
char *msg = "XXX Connection established\n\r";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
user_data->conn_XXX = newconn;
}
}
else
{
char *msg = "Error in acceptation TCP XXX connection\n\r";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
print_error(error_accept);
}
return 0;
}
The strange thing is, that when i only create 2 netconn structure, i have no problem with the 2 connection in the same time.
What can cause the connexion aborted ?
How can i get the 3 connection in the same time ?
If it is possible of course ...
Ok, yes after 1day of testing,
the param
#define MEMP_NUM_NETCONN 4
is definetly what makes me troubl.
i just have to set it to 10, and everything works like a charm
Related
I have two nodes of wso2-am analytics server (2.6.0) which is Wso2 Stream processors. I see following error on passive node of cluster. The active node is fine and I don't see any error. Analytics result has no impact for users who is viewing data on API Publisher or Store. however there is an error in passive node.
please advise what is causing following issue..
2019-02-26 17:06:09,513] ERROR {org.wso2.carbon.stream.processor.core.ha.tcp.EventSyncServer} - Error occurred while processing eventByteBufferQueue null java.nio.BufferUnderflowException
Just meet the same issue, here is my problem and solution.
1) Using the WSO2 SP HA deployment.
2) When Event come in active node and according the source mapping of the streaming, some fields are NULL
3) Active Node would like sync this event to passive node
4) passive node pick up the event data from the 'eventByteBufferQueue' to meet the standby-take over mechanism
5) passive node cannot parse the data from active node and reports error exception.
the root cause is SP only support NULL String by default, when NULL with LONG, INTEGER.. the error occurred. but for me, Long fields have NULL is the normal case, you can change data type to string.
here is my solution:
org.wso2.carbon.stream.processor.core_2.0.478.jar
Add logic to support NULL
BinaryMessageConverterUtil.java for sending event data from active node
public final class BinaryMessageConverterUtil {
public static int getSize(Object data) {
if (data instanceof String) {
return 4 + ((String) data).length();
} else if (data instanceof Integer) {
return 4;
} else if (data instanceof Long) {
return 8;
} else if (data instanceof Float) {
return 4;
} else if (data instanceof Double) {
return 8;
} else if (data instanceof Boolean) {
return 1;
} else if (data == null) {
return 0;
}else {
//TODO
return 4;
}
}
public static EventDataMetaInfo getEventMetaInfo(Object data) {
int eventSize;
Attribute.Type attributeType;
if (data instanceof String) {
attributeType = Attribute.Type.STRING;
eventSize = 4 + ((String) data).length();
} else if (data instanceof Integer) {
attributeType = Attribute.Type.INT;
eventSize = 4;
} else if (data instanceof Long) {
attributeType = Attribute.Type.LONG;
eventSize = 8;
} else if (data instanceof Float) {
attributeType = Attribute.Type.FLOAT;
eventSize = 4;
} else if (data instanceof Double) {
attributeType = Attribute.Type.DOUBLE;
eventSize = 8;
} else if (data instanceof Boolean) {
attributeType = Attribute.Type.BOOL;
eventSize = 1;
} else if (data == null){
attributeType = Attribute.Type.OBJECT;
eventSize = 0; //'no content between the HA nodes for NULL fields'
} else {
//TODO
attributeType = Attribute.Type.OBJECT;
eventSize = 1;
}
return new EventDataMetaInfo(eventSize, attributeType);
}
public static void assignData(Object data, ByteBuffer eventDataBuffer) throws IOException {
if (data instanceof String) {
eventDataBuffer.putInt(((String) data).length());
eventDataBuffer.put((((String) data).getBytes(Charset.defaultCharset())));
} else if (data instanceof Integer) {
eventDataBuffer.putInt((Integer) data);
} else if (data instanceof Long) {
eventDataBuffer.putLong((Long) data);
} else if (data instanceof Float) {
eventDataBuffer.putFloat((Float) data);
} else if (data instanceof Double) {
eventDataBuffer.putDouble((Double) data);
} else if (data instanceof Boolean) {
eventDataBuffer.put((byte) (((Boolean) data) ? 1 : 0));
} else if (data == null){
//put nothing into he Buffer
} else {
eventDataBuffer.putInt(0);
}
}
public static String getString(ByteBuf byteBuf, int size) throws UnsupportedEncodingException {
byte[] bytes = new byte[size];
byteBuf.readBytes(bytes);
return new String(bytes, Charset.defaultCharset());
}
public static String getString(ByteBuffer byteBuf, int size) throws UnsupportedEncodingException {
byte[] bytes = new byte[size];
byteBuf.get(bytes);
return new String(bytes, Charset.defaultCharset());
}
}
SiddhiEventConverter.java for processing event data at passive node
static Object[] toObjectArray(ByteBuffer byteBuffer,
String[] attributeTypeOrder) throws UnsupportedEncodingException {
if (attributeTypeOrder != null) {
Object[] objects = new Object[attributeTypeOrder.length];
for (int i = 0; i < attributeTypeOrder.length; i++) {
switch (attributeTypeOrder[i]) {
case "INT":
objects[i] = byteBuffer.getInt();
break;
case "LONG":
objects[i] = byteBuffer.getLong();
break;
case "STRING":
int stringSize = byteBuffer.getInt();
if (stringSize == 0) {
objects[i] = null;
} else {
objects[i] = BinaryMessageConverterUtil.getString(byteBuffer, stringSize);
}
break;
case "DOUBLE":
objects[i] = byteBuffer.getDouble();
break;
case "FLOAT":
objects[i] = byteBuffer.getFloat();
break;
case "BOOL":
objects[i] = byteBuffer.get() == 1;
break;
case "OBJECT":
//for NULL fields
objects[i] = null;
break;
default:
// will not occur
}
}
return objects;
} else {
return null;
}
}
When see the qt source code(QEventDispatcherWin32::processEvents),i find a Logical issues.code as below,first it writes if(!haveMessage) next if(haveMessage),so code else if (...) and else{...} will never execute,what i think is right?
code as:
if (!haveMessage) {
// no message - check for signalled objects
for (int i = 0; i < (int)nCount; i++)
pHandles[i] = d->winEventNotifierList.at(i)->handle();
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
// a new message has arrived, process it
continue;
}
}
if (haveMessage) {
#ifdef Q_OS_WINCE
// WinCE doesn't support hooks at all, so we have to call this by hand :(
(void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM)&msg);
#endif
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
if (seenWM_QT_SENDPOSTEDEVENTS) {
// when calling processEvents() "manually", we only want to send posted
// events once
needWM_QT_SENDPOSTEDEVENTS = true;
continue;
}
seenWM_QT_SENDPOSTEDEVENTS = true;
}
else if (msg.message == WM_TIMER) {
// avoid live-lock by keeping track of the timers we've already sent
bool found = false;
for (int i = 0; !found && i < processedTimers.count(); ++i) {
const MSG processed = processedTimers.constData()[i];
found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
}
if (found)
continue;
processedTimers.append(msg);
}
else if (msg.message == WM_QUIT) {
if (QCoreApplication::instance())
QCoreApplication::instance()->quit();
return false;
}
if (!filterEvent(&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
}
else {
// nothing todo so break
break;
}
Is there any way to detect if my computer is connected via cable or mobile network to the internet?
I tried to analyze the trace-route output but realized that it would need a very large and up-to-date database to detect the type of network the data packages take.
Have this two different types of network maybe some different attributes that are easily to detect?
You can use the NetworkListManager APIs to find if a network is connected to the internet. The example below does both that and checks to see if the network is free. You can just remove the Cost related code:
HRESULT GetFreeInternetInterface(_Out_ GUID* pInterfaceGuid)
{
bool fCoInitialized = false;
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
fCoInitialized = true;
CComPtr<INetworkListManager> pNetworkListManager;
hr = pNetworkListManager.CoCreateInstance(__uuidof(NetworkListManager));
if (SUCCEEDED(hr))
{
CComPtr<IEnumNetworkConnections> pNetworkConnections;
hr = pNetworkListManager->GetNetworkConnections(&pNetworkConnections);
bool fFound = false;
while (SUCCEEDED(hr))
{
CComPtr<INetworkConnection> pNetworkConnection;
hr = pNetworkConnections->Next(1, &pNetworkConnection, nullptr);
if (hr == S_OK)
{
CComPtr<INetworkConnectionCost> pNetworkConnectionCost;
hr = pNetworkConnection.QueryInterface(&pNetworkConnectionCost);
if (SUCCEEDED(hr))
{
NLM_CONNECTIVITY nlmConnectivity = NLM_CONNECTIVITY_DISCONNECTED;
DWORD dwCost = NLM_CONNECTION_COST_UNKNOWN;
if (SUCCEEDED(pNetworkConnection->GetConnectivity(&nlmConnectivity)) &&
(nlmConnectivity & (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET)) != 0 &&
SUCCEEDED(pNetworkConnectionCost->GetCost(&dwCost)) &&
dwCost == NLM_CONNECTION_COST_UNRESTRICTED &&
SUCCEEDED(pNetworkConnection->GetAdapterId(pInterfaceGuid)))
{
fFound = true;
break;
}
}
}
else hr = E_NOINTERFACE;
}
if (SUCCEEDED(hr) && !fFound)
hr = E_NOINTERFACE;
}
}
if (fCoInitialized) CoUninitialize();
return hr;
}
Once you have the interface GUID and IP Helper APIs to get the interface type. Here is some code I had that looks for non-cellular networks. You can take it and modify it to do what you need:
BOOL GetAdapterAddresses(
_Out_ PIP_ADAPTER_ADDRESSES * ppIAA
)
{
*ppIAA = NULL;
DWORD len = 0;
DWORD flags = GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER;
if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len) != ERROR_BUFFER_OVERFLOW)
return FALSE;
PIP_ADAPTER_ADDRESSES pIAA = (PIP_ADAPTER_ADDRESSES)LocalAlloc(LPTR, len);
if (pIAA) {
GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pIAA, &len);
*ppIAA = pIAA;
return TRUE;
}
return FALSE;
}
bool IsNonCellularIfType(
_In_ IFTYPE IfType
)
{
return // Ignore Loopback and WWAN
IfType != IF_TYPE_SOFTWARE_LOOPBACK &&
IfType != IF_TYPE_WWANPP &&
IfType != IF_TYPE_WWANPP2;
}
DWORD GetNonCellularIfIndex(
)
{
DWORD IfIndex = (DWORD)(-1);
PIP_ADAPTER_ADDRESSES pIAA;
if (GetAdapterAddresses(&pIAA)) {
PIP_ADAPTER_ADDRESSES pIAAList = pIAA;
while (pIAA) {
// Look for Non-Cellular interface
if (pIAA->OperStatus == IfOperStatusUp &&
IsNonCellularIfType(pIAA->IfType)) {
PIP_ADAPTER_UNICAST_ADDRESS_LH pUnicastAddr = pIAA->FirstUnicastAddress;
// Look through all unicast addresses for valid IPv4 or IPv6 addresses
while (pUnicastAddr) {
LPSOCKADDR pAddr = pUnicastAddr->Address.lpSockaddr;
if (pAddr->sa_family == AF_INET) {
if (!IN4_IS_ADDR_LINKLOCAL(&((SOCKADDR_IN *)pAddr)->sin_addr)) {
IfIndex = pIAA->IfIndex;
break;
}
}
else if (pAddr->sa_family == AF_INET6) {
if (!IN6_IS_ADDR_LINKLOCAL(&((SOCKADDR_IN6 *)pAddr)->sin6_addr)) {
IfIndex = pIAA->IfIndex;
break;
}
}
pUnicastAddr = pUnicastAddr->Next;
}
// No need to keep looking any more?
if (IfIndex != (DWORD)(-1))
break; // while (pIAA)
}
pIAA = pIAA->Next;
}
LocalFree(pIAAList);
}
return IfIndex;
}
I'm trying to create simple app using raw tcp api from lwip package.
So, here is part of my code:
err_t net_dg_accept(void *arg, struct tcp_pcb *con, err_t e)
{
stm_debug("netdebug: accepting connection");
const char *msg_t = "This is test debug message";
tcp_write(con, msg_t, sizeof(msg_t),TCP_WRITE_FLAG_COPY);
tcp_close(con);
}
void net_dg_thread ()
{
stm_debug("netdebug: thread is starting");
thrd_pcb = tcp_new();
if (thrd_pcb != NULL)
{
stm_debug("netdebug: thread_pcb was created");
err_t e;
e = tcp_bind(thrd_pcb, IP_ADDR_ANY, 22);
if (e == ERR_OK)
{
stm_debug("netdebug: thread_pcb was binded!");
lpcb = tcp_listen(thrd_pcb);
stm_debug("netdebug: thread_pcb was put into listenning mode!");
tcp_accept(lpcb,net_dg_accept);
stm_debug("netdebug: ?");
}
else
{
stm_debug("netdebug: error while binding thread_pcb!");
}
}
else
{
stm_debug("netdebug: error while creating thread_pcb!");
}
}
I try to connect to 22 port, but I get nothing. From the serial debug I get that thrd_pcb was successfully put into listening mode. Why can it be so?
I am receiving an odd error with my scanner integration. I am making use of an OPOS scanner in my program. When the program closes I disable, release and close the device, but no other application can use it after my program runs. Also if I restart no application can use it. Not even my application which causes the issue. I did find that if I do not claim the device the issue doesn't happen. I am currently trying to get a fresh copy of the DLL in case the release method is somehow corrupted? Any other ideas?
public bool InitBarcode(bool overrideLGBarcode)
{
Util.LogMessage("Initializing barcode scanner!");
if (_barcodeScanner == null)
{
Util.LogMessage("Barcode scanner was null. instantiating a new one");
_barcodeScanner = new OPOSScanner();
_barcodeScanner.AutoDisable = true;
_barcodeScanner.DataEvent += BarcodeDataEventHandler;
Util.LogMessage("Added event handler");
}
else
{
Util.LogMessage("Barcode scanner was not null");
}
if (_barcodeScanner.Open("STI_USBSCANNER") != 0)
{
Util.LogMessage("Barcode scanner \"STI_USBSCANNER\" could not be opened!");
return false;
}
else
{
Util.LogMessage("STI_USBSCANNER was opened");
}
int result = _barcodeScanner.ClaimDevice(-1);
Util.LogMessage("Claiming barcode scanner returned result: " + result);
_barcodeScanner.DecodeData = true;
_barcodeScanner.DeviceEnabled = true;
_barcodeScanner.DataEventEnabled = true;
return true;
}
public void CloseBarcode()
{
Util.LogMessage("Disabling, Releasing and Closing the barcode scanner!");
_barcodeScanner.DataEvent -= BarcodeDataEventHandler;
Util.LogMessage("Removed event handler");
_barcodeScanner.AutoDisable = false;
_barcodeScanner.DecodeData = false;
_barcodeScanner.DataEventEnabled = false;
_barcodeScanner.DeviceEnabled = false;
if (_barcodeScanner.DeviceEnabled != false)
{
Util.LogMessage("Barcode scanner could not be disabled!");
}
else
{
Util.LogMessage("Barcode scanner was disabled!");
}
int result = _barcodeScanner.ReleaseDevice();
Util.LogMessage("ReleseDevice() yielded result of: " + result);
if (result != 0)
{
Util.LogMessage("Barcode scanner could not be released!");
}
else
{
Util.LogMessage("Barcode scanner was released!");
}
if (_barcodeScanner.Close() != 0)
{
Util.LogMessage("Barcode scanner could not be closed!");
}
else
{
Util.LogMessage("Barcode scanner was closed!");
}
_barcodeScanner = null;
}