|
|
Edit
Since the server is in listen /accept waiting mode all I should worry about timeout.
I can set the socket to take care of that.
I just test client to send multiple single message - in 5 second interval and reinitialized the client socket each time. Works fine for my task.
It has been a challenge , but I finally have bluetooth connection passing simple text message from client to server.
My task is to be able to utilize such connection as necessary, hence not keeping it in any kinda-of synchronous loop.
At present the communication will always be from client to server , and started by client. .
Basically I am looking for a way to check "is server connected ? ".
I do not see any issues closing the client socket and reinitializing it when new communication is required.
I hope I can instruct server socket (timeout ?) to stay connected in "accept" function...
However, I have been reading up on "select"
<a href="http://man7.org/linux/man-pages/man2/select_tut.2.html">select_tut(2) - Linux manual page</a>[<a href="http://man7.org/linux/man-pages/man2/select_tut.2.html" target="_blank" title="New Window">^</a>]
and wondering if that woudl be "cleaner" way to run this asynchronously by monitoring the state of the connection when necessary.
Maybe I'll be over my head again using select...
Any commentaries (to the subject) or other suggestion will be appreciated.
modified 7-Mar-20 16:40pm.
|
|
|
|
|
This is NOT question, just asking - to whom do I trust ?
perror posts “operation now in progress “ which is great to know
BUT connect return “status “ is -1 .
To whom do I trust ?
This implies that "“operation now in progress “ is an error or checking return value is bogus.
Simple "connect" function description quoted from documentation:
"The normal return value from connect is 0. If an error occurs, connect returns -1. The following errno error conditions are defined for this function:"
Please notice how "errno" is used.
status = connect(s, (struct sockaddr*) &server_addr, sizeof(server_addr));
if (errno != 0 | status != 0) { // redundant and wrong
....
|
|
|
|
|
Both.
From the man page:
Quote: RETURN VALUE
If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
The following are general socket errors only. There may be other domain-specific error codes.
EACCES For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file, or
search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)
EACCES, EPERM
The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the connec‐
tion request failed because of a local firewall rule.
EADDRINUSE
Local address is already in use.
... etc ...
So you know that the call to connect() did not succeed, because it returned -1. There's a lot of reasons that connect() might fail, and you can examine errno to find out why. In many cases, depending on context, an unsuccessful connect might be expected, or recoverable (e.g. if you've run out of resources, you might be able to either wait for other connections to close, or be able to clean up/close old connections). In your case errno is EINPROGRESS "The socket is nonblocking and the connection cannot be completed immediately". See the man page for further information. If this is a bluetooth, then consult any relevant bluetooth docs to see if EINPROGRESS is mentioned and why you might get that error code.
Note that perror() will always print "operation now in progress" any time errno == EINPROGRESS. Some library calls might set EINPROGRESS to indicate a condition that does not directly translate to "operation now in progress", but the resource is temporarily busy, and you should try again later, and EAGAIN already is used for some other retry condition.
|
|
|
|
|
"So you know that the call to connect() did not succeed, because it returned -1. There's a lot of reasons that connect() might fail, and you can examine errno to find out why."
That is what I though I was doing - looking at status and expected 0 and then errno to get some more info.
I think the connect is failing due to remote end not responding in - for now unknown - time, but that is where the "in progress" is somewhat telling me that.
Also the actual response is delayed by this , yet unspecified time.
Interestingly - after first call fails with "in progress..." next call returns immediately with "device busy..".
Question is - which device ?
Must be the local which is busy - doing what ? It did not connect...
Remote ? If it did not "connect" in first place how it can be the remote which is busy?
( At present rebooting local sort of works, and I am working on something faster using code ...)
"Note that perror() will always print "operation now in progress" any time errno == EINPROGRESS"
I don't think there is an easy way to correlate actual message to its symbol.
I am sure I can find the source code , but why ?
In my view that woudl defeat the function of perror - translating the errno # to text without showing the symbols.
|
|
|
|
|
The "in progress" status is telling you that the local device is trying to complete some operation. If you then try to use it again it may well be returning "busy" because it is unable to accept your request.
The perror() function has been around for years and has always been fairly succinct in its output. The important information is the actual errno value. It is a fairly simple matter to write your own function to display the value and the error message (see strerror(3) - Linux manual page[^]).
What you really should do is get hold of the RFC documents for TCP/IP and Bluetooth, and study the protocol details. They should give you the exact sequence of events that are supposed to happen when the two endpoints try to communicate.
|
|
|
|
|
Richard MacCutchan wrote: The perror() function has been around for years and has always been fairly succinct in its output. The important information is the actual errno value. It is a fairly simple matter to write your own function to display the value and the error message (see strerror(3) - Linux manual page[^]).
Even old dogs learn something new occasionally. I was certain that perror() would be locale aware, but it seems not (which could be an issue if you are depending on exact text matches in your output). While researching that, I came across the GNU error() function, which might help the OP. See about half-way down this page: Error Messages (The GNU C Library)
|
|
|
|
|
Thanks, this is very good reference.
Error Messages (The GNU C Library)[^]
So far I am getting used to perror , it mostly gives good description of the state.
I am still unsure how to recover from some of those related to socket and bluetooth.
The moral of the story
check the return value first , then let perror describe the state.
perror does not always tells error, but state.
BTW the original error was due to my mistake not checking the remote bluetooth device address.
I was passing the device name and not the address!
Live and learn...
Cheers
|
|
|
|
|
Vaclav_ wrote: check the return value first , then let perror describe the state. No, don't rely on perror alone. The most important piece of information is the actual error code. And, as I already suggested, you should study the RFC documents to get a thorough understanding of the protocols you are trying to use.
|
|
|
|
|
Quote: The important information is the actual errno value. It is a fairly simple matter to write your own function to display the value and the error message (see strerror(3) - Linux manual page[^]).
You don't need to, on GNU systems simply use '%m' in the printf format string. The '%m' is replaced with the actual error message in the language that the system is set to.
|
|
|
|
|
I think this question was well answered 9 months ago.
|
|
|
|
|
Quote: perror posts “operation now in progress “ which is great to know
BUT connect return “status “ is -1 .
To whom do I trust ?
They're both saying the same thing. Why are you confused? The return from connect() means "Unable to connect, check errno for why". The errno you are getting for "why I can't connect" is "operation in progress (EINPROGRESS)".
Seems pretty clear.
|
|
|
|
|
This is pretty simple function and compiles and works fine on X86.
Same usage , with same parameters passed to it, fails on ARM.
Description Resource Path Location Type
cannot convert ‘sockaddr_rc’ to ‘char*’ for argument ‘2’ to ‘int ba2str(const bdaddr_t*, char*)’ CBT.cpp /RPI_BT_CLIENT_ARM_/src/MODULES/M_CBT line 286 C/C++ Problem
I am at lost and could use some help to make it work.
It it helps, here is the code
for (i = 0; i < num_rsp; i++) {
ba2str(&(ii + i)->bdaddr, addr); FAILS HERE
memset(name, 0, sizeof(name));
if (hci_read_remote_name(dev_descriptor, &(ii + i)->bdaddr,
sizeof(name), name, 0) < 0)
strcpy(name, "[unknown]");
printf("remote address %s remote name %s\n", addr, name);
}
Bluetooth addresses are a 6-byte hex number similar to an Ethernet MAC address. BlueZ provides convenience functions for converting between a 6-byte string in the format 00:11:22:33:44:55 and the bdaddr_t struct. Here are the function prototypes:
int ba2str(const bdaddr_t *ba, char *str);
int str2ba(const char *str, bdaddr_t *ba);
The function ba2str converts from the internal bdaddr_t to a zero-terminated string (the str parameter should have at least 18 bytes), and str2ba provides the opposite conversion. The first example makes use of the ba2str function.
|
|
|
|
|
I don't see a question.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
len = 8;
max_rsp = 255;
flags = IREQ_CACHE_FLUSH;
ii = (inquiry_info*) malloc(max_rsp * sizeof(inquiry_info));
cout << "TASK run hci_inquiry same as hcitoo scan - takes time @line "
<< dec << __LINE__ << endl;
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
perror("STATUS hci_inquiry");
errno = 0;
if (num_rsp < 0)
perror("FAILED (?) hci_inquiry");
for (i = 0; i < num_rsp; i++) {
ba2str(&(ii + i)->bdaddr, addr);
memset(name, 0, sizeof(name));
if (hci_read_remote_name(dev_descriptor, &(ii + i)->bdaddr,
sizeof(name), name, 0) < 0)
strcpy(name, "[unknown]");
printf("remote address %s remote name %s\n", addr, name);
}
the question is
WHY does highlighted code throws an error
|
|
|
|
|
No idea, because you have not told us what the error is.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
in
ba2str(&(ii + i)->bdaddr, addr); what is the type of addr ? It should be of type char * , but your compiler is telling you its of type sockaddr_rc . Have you managed to "shadow" the addr varialbe (e.g)
char addr[18];
for( ) {
sockaddr_rc addr;
ba2str( );
}
Maybe try adding -Wshadow to your compiler options to find out.
|
|
|
|
|
There's absolutely no way to tell given what you've shown us. You have given us no details on where, when or how its failing for your use case. Nor have you told us wht "fails" means in your context. Most likely, you have a bad baddr_t* passed in to ba2str() , or you have passed in a const char * , but have cast away const-ness somewhere. Does ba2str() produce any diagnostics (e.g. set an error code like errno, or indicate failure reason in its return code) that would help narrow down why it "fails"?
|
|
|
|
|
You just need to cast the addr parameter to a char* as mentioned in the error message. See also https://people.csail.mit.edu/albert/bluez-intro/c404.html[^], where addr is a char array.
So you can change to
for (i = 0; i < num_rsp; i++) {
ba2str(&(ii + i)->bdaddr, (char*)addr); memset(name, 0, sizeof(name));
if (hci_read_remote_name(dev_descriptor, &(ii + i)->bdaddr,
sizeof(name), name, 0) < 0)
strcpy(name, "[unknown]");
printf("remote address %s remote name %s\n", addr, name);
}
|
|
|
|
|
Richard,
there is something else wrong here.
After I cast (char*) addr it complains abut wrong type.
I need to go and check the ba2str source , perhaps read the results of hci_inquiry
before converting to addr.
It is puzzling why it works on X86, hope it is not yet another "64 bits / 32 bits " issue.
Description Resource Path Location Type
invalid cast from type ‘sockaddr_rc’ to type ‘char*’ CBT.cpp /RPI_BT_CLIENT_ARM_/src/MODULES/M_CBT line 286 C/C++ Problem
|
|
|
|
|
Sorry, I missed the fact that addr is not a pointer (as shown in that link I gave you). Try:
ba2str(&(ii + i)->bdaddr, (char*)&addr);
Or better still use a char array as in the example.
|
|
|
|
|
Mea culpa!
I need to get this client / server code mess under control.
Way too many "addresses" and yet another "shadow" error.
Thanks to all of you it is fixed!
I need to pay better attention to the complier errors - this time it pointed me to "shadows".
Adding the check for it as standard complier option from now on.
Cheers
|
|
|
|
|
I have been writing code using crosscomplier for ARM architecture.
Works as expected. No "cast looses precision " errors.
Now I optioned IDE to change the architecture to X86.
Compiler now complains about
"cast looses precision " .
The complains (too many) are in class I am currently NOT editing.
Is there a option I can set GCC to temporary ignore
"cast looses precision " errors ?
Since the
"cast looses precision " was not present while compiling for ARM it would not hurt to know WHY it fails in X86.
Here is the IDE "error"
Description Resource Path Location Type
cast from ‘uint32_t* {aka unsigned int*}’ to ‘uint32_t {aka unsigned int}’ loses precision [-fpermissive] CBCM2835SPITFT.cpp /RPI_BT_SERVER_X86_/src/MODULES/M_BCM2835_SPI_TFT line 21264 C/C++ Problem
And here ONE of the offending code
bcm2835_peripherals = (uint32_t*) mapmem(
NULL, bcm2835_peripherals_size, _memfd, (uint32_t) bcm2835_peripherals_base);
Cheers
PS I think wholesale "search and replace " is too risky.
PPS Does the architecture - 64 bits on X86 and 32 on ARM matter? - both Linux OS.
|
|
|
|
|
That is because you are trying to cast a pointer to a unint32_t (i.e. a memory address) to an actual uint32_t (i.e. an integer variable). And the pointer may well be larger than 32 bits, so the compiler is warning you that the resulting value may not be what you expect.
|
|
|
|
|
The compiler is complaining that you are casting a pointer to uint32_t (which is 64 bits on Linux built for x86_64) to uint32_t (which is 32 bits). You are losing half of the pointer, which is guaranteed not to end well.
The ARM code was compiled for a 32-bit ARM. If you wish to compile the code for a 64-bit processor, you will have to go carefully through the code, examining each cast and ensuring that it is still valid.
One way to make this (slightly...) less painful would be to use the C99 type uintptr_t (defined in stdint.h) or the C++ type std::uintptr_t (defined in cstdint), which gives you an integer type guaranteed to hold a pointer. You must then ensure that your structures are correctly defined.
All in all, converting a program from 32-bit to 64-bit is a non-trivial task...
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|