How to use getaddrinfo()? - winsock

Im trying to make a simple program that takes in a string like www.google.com and returns the ip address...
What i have so far:
char* hostname = new char[www.size()+1];
std::copy(www.begin(), www.end(), hostname);
hostname[www.size()] = '\0';
struct addrinfo new_addr, *res;
getaddrinfo(www.c_str(), SERVICE.c_str(), &new_addr, &res);
cout << new_addr.ai_addr;
What are the 3rd of 4th parameters supposed to do? Does the getaddrinfo function modify the new_addr structure or what? I dont really understand the msdn documentation. After the hostname is resolved I want to connect a socket to it.

What if i leave the third parameter nullified?
Heres the code i developed so far.
char* hostname = new char[www.size()+1];
copy(www.begin(), www.end(), hostname);
hostname[www.size()] = '\0';
struct addrinfo *res;
struct in_addr addr;
getaddrinfo(hostname, NULL, 0, &res);
addr.S_un = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.S_un;
server.sin_addr.s_addr = inet_addr(inet_ntoa(addr));
server.sin_port = htons(portno);
freeaddrinfo(res);
delete []hostname;
server.sin is declared elsewhere that i use to fill a socket in another method of my sockets class.

The MSDN documentation is very detailed and explains exactly what the various parameters are for. The third parameter lets you specify the type of socket that will be used with the results of the lookup. This allies the results to be optimized as needed. The fourth parameter returns the actual results. The documentation also contains a full example of how to use the function. So what example is unclear about what the documentation says?
Try this:
struct addrinfo hints = {0};
hints.ai_flags = 0;
hints.ai_family = AF_UNSPEC; // IPv4 and IPv6 allowed
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo *res = NULL;
if (getaddrinfo(www.c_str(), SERVICE.c_str(), &hints, &res) == 0)
{
TCHAR szIPAddr[64];
DWORD szIPAddrLen;
SOCKET skt;
struct addrinfo *addr = res;
do
{
skt = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (skt == INVALID_SOCKET)
cout << "Unable to create socket, error " << WSAGetLastError() << endl;
else
{
szIPAddrLen = 64;
WSAAddressToString(addr->ai_addr, addr->ai_addrlen, NULL, szIPAddr, &szIPAddrLen);
cout << "Connecting to " << szIPAddr << " ..." << endl;
if (connect(skt, addr->ai_addr, addr->ai_addrlen) == 0)
{
cout << "Connected!" << endl;
break;
}
cout << "Unable to connect, error " << WSAGetLastError() << endl;
closesocket(skt);
skt = INVALID_SOCKET;
}
addr = addr->ai_next;
}
while (addr);
freeaddrinfo(res);
if (skt != INVALID_SOCKET)
{
// use skt as needed...
closesocket(skt);
}
}

Related

recvfrom returning errno 14 in debug mode with GDB

I have a code something like this.
where recvfrom works fine if i run the code normally. but when i run the code with GDB, recvfrom doesn't wait for 2 seconds and instantly throwing errno 14.
==
char buf[sizeof(FSME_START)] = { 0 };
/* open socket */
fsm_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fsm_fd < 0)
{
perror("socket");
exit(1);
}
const struct sockaddr_in remote_addr = { .sin_family = AF_INET };
//socklen_t addrlen = sizeof(struct sockaddr);
socklen_t addrlen = sizeof(client_addr);
struct timeval tv = { .tv_sec = 2,
.tv_usec = 0};
/* set initial 1s recv timeout */
int ret = setsockopt(fsm_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
if (ret < 0)
{
perror("setsockopt");
exit(1);
}
while (1)
{
const struct iovec iov = { .iov_base = (void*)FSME_START,
.iov_len = sizeof(FSME_START) };
// Send the START packet (once/sec) to the FSM-E until we get
// receive a START message back based on 1sec timeout set above.
fsm_dp_send(&iov,1,0);
ret = recvfrom(fsm_fd, (char *)buf, MAX_BUFSIZE,
MSG_WAITALL, (struct sockaddr *)&client_addr, &addrlen);
====
I tried passing client_addr and addrlen both parameters as NULL but no success. But strangely this code works if run without GDB.
Any suggestions
looks like there is an error with the size of msg i was passing with recvfrom but it was weird that one version of gdb and and even compiler was hiding this error. This error was visible only with older gdb version. Later on when i passed the correct size of the buffer, it was passing.

Error with sendto() function: Invalid Argument Error

I am working on writing a ping CLI program for linux and I have been getting errno 22: invalid argument in the sendto() function. I don't understand why, all the arguments seem to be correct.
Here is where I call the function:
// send echo request
bytesSent = sendto(socketFD, // socket file descriptor
(char*)&packet, PacketSize, // packet and size
0, // flags
(sockaddr*)DestinationAddr, (socklen_t)sizeof(DestinationAddr)); // destination address and size
'packet' looks like this:
(I call initializePacket() in the function where I call sendto())
struct PacketData {
icmphdr header;
char message[PacketSize - sizeof(header)]; // want total size to be 64 bytes
};
PacketData initializePacket(int &transmitted) {
PacketData packet = {};
packet.header.type = ICMP_ECHO; // set ICMP type to Echo
packet.header.un.echo.id = getpid() & 0xFFFF; // set id (ICMP field is 16 bits)
packet.header.checksum = 0; // fixed checksum because data is unchanging
packet.header.un.echo.sequence = transmitted++;
// fill up message
memset(&packet.message, '0', sizeof(packet.message));
packet.message[PacketSize - sizeof(packet.header) - 1] = '\0';
return packet;
}
'DestinationAddr' is this:
// variables needed to store IP Address
addrinfo* result;
sockaddr_in* DestinationAddr;
char ipString[INET_ADDRSTRLEN];
// get IP Address and store in result (passed by reference)
if (getIPAddress(argv[1], result) != 0) {
std::cout << "Invalid IP Address. Terminating ...\n";
exit(EXIT_FAILURE);
}
else {
DestinationAddr = (sockaddr_in*)result->ai_addr; // get struct from resulting linked list
void* address;
address = &DestinationAddr->sin_addr; // store IP Address
inet_ntop(result->ai_family, address, ipString, sizeof(ipString)); // convert binary IP to string
std::cout << "IP: " << ipString << std::endl;
}
And the getIPAddress() function is:
int getIPAddress(char* hostName, addrinfo* &result) {
addrinfo tempStruct = {0};
tempStruct.ai_family = AF_INET; // want IPv4
tempStruct.ai_socktype = SOCK_DGRAM; // set socket type to datagram
tempStruct.ai_flags = AI_PASSIVE; // fill in IP automatically
// get and validate IP address
return (getaddrinfo(hostName, &PortNo, &tempStruct, &result));
}
PortNo is defined as: const char PortNo = '0';
According to documentation icmp:
A user protocol may receive ICMP packets for all local sockets by opening a raw socket with the protocol IPPROTO_ICMP.
So, try creating your socket like that:
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
And, if you encounter EPERM error, then run your program as root.

is there a working vmci example?

I need a working VMCI socket example that does what UDP does, but without networking. There are many good code fragments in the vmci_sockets.h code, but not a full working template to expand on.
I believe that the server should look as follows:
#include "vmci_sockets.h"
#define BUFSIZE 2048
int main() {
int afVMCI = VMCISock_GetAFValue();
if ((sockfd_dgram = socket(afVMCI, SOCK_DGRAM, 0)) == -1) {
perror("socket");
goto exit;
}
struct sockaddr_vm my_addr = {0};
my_addr.svm_family = afVMCI;
my_addr.svm_cid = VMADDR_CID_ANY;
my_addr.svm_port = VMADDR_PORT_ANY;
if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof my_addr) == -1) {
perror("bind");
goto close;
}
if (getsockname(sockfd, (struct sockaddr *) &my_addr, &svm_size) == -1) {
perror("getsockname");
goto close;
}
if ((numbytes = recvfrom(sockfd, buf, sizeof buf, 0,
(struct sockaddr *) &their_addr, &svm_size)) == -1) {
perror("recvfrom");
goto close;
}
close:
return close(sockfd);
}
and for the client
#include <stdio.h>
#include <string.h>
#include "vmci_sockets.h"
#define BUFSIZE 128
int main() {
int afVMCI = VMCISock_GetAFValue();
int fd;
struct sockaddr_vm addr;
if ((fd = socket(afVMCI, SOCK_DGRAM, 0)) == -1) {
perror("socket");
return 1;
}
addr.svm_family = afVMCI;
addr.svm_cid = VMADDR_CID_ANY;
addr.svm_port = VMADDR_PORT_ANY;
bind(fd, (struct sockaddr *) &addr, sizeof addr);
struct sockaddr_vm serveraddr;
socklen_t svm_size = sizeof serveraddr;
{
int numbytes; char buf[BUFSIZE]; bzero(buf, BUFSIZE);
strcpy(buf, "hello there\n");
if ((numbytes = sendto(fd, buf, BUFSIZE, 0,
(const struct sockaddr *) &serveraddr, svm_size)) == -1) {
perror("sendto error");
goto close;
}
}
close:
close(fd);
VMCISock_ReleaseAFValueFd(fd);
return 0;
}
however, it's not working. there is not much documentation, e.g., how to troubleshoot. there is not information whether one can try both server and client within the same virtual machine for debugging purposes.
I tried to post to the vmware board, sent an email to their support, but no one seems to have a working example. because this is not standard socketry, though it is similar socketry, it is and is not followable.
anyone have a working example?
vmci is apparently not supported for vmplayer or vmware fusion. this is what the vmware support people told me:
I have been checking internally with our development team regarding
your request and incidentally could only generate interest if this was
a situation that is failing with vSphere. The final comment I have is
that we never meant to officially support this for VMware Fusion and
certain dependencies are on internal references only.
Unfortunately, we do not have any such vmci example which can be
shared publicly when it comes to VMware Fusion.

Is there a function in gtkmm that reads from FileInputStream in the way that can then be used to set the TextArea

I'm trying to read text from file and put it in the TextView. FileInputStream has read_bytes, there is set_text in TextBuffer that can take ustring, but there seem to be no way to go from one to another.
In the InputStream's child classes i found DataInputStream which does have read_line_utf8 giving one an std::string (better than nothing), but even DataInputStream is on the separate class hierarchy branch from FileInputStream.
Of course, theoretically it is possible to just cycle through the array of bytes returned by the read_bytes and turn them into characters, but somehow i just refuse to believe that there is no ready function that i'm overlooking.
Ultimately i'm looking for a function that would take Glib::RefPtr<Glib::Bytes> and return me a Glib::ustring
OK, after searching far and wide i have managed to confirm that there is no way to do so within the confines of gtkmm library. This does seem pretty strange to me, but there it is.
So here is how to read the file via the normal tools, then convert what you've read, and display it in the TextArea:
I assume here that you've already opened the dialog and connected all that needs to be connected for it. If you have a Controller class you will end up with something along the lines of:
fh = dialog->get_file();
fh->read_async( sigc::mem_fun( *this, &Controller::on_file_read_complete ));
Make sure that you have Glib::RefPtr< Gio::File > fh; as the private data member and not as a local variable. You will then need a function on_file_read_complete
void Controller::on_file_read_complete(Glib::RefPtr<Gio::AsyncResult>& res)
{
Glib::RefPtr<Gio::InputStream> fin = fh->read_finish(res);
Glib::RefPtr<Glib::Bytes> fbytes = fin->read_bytes(8192, Glib::RefPtr<Gio::Cancellable>());
Glib::ustring str = bytesToUstring(fbytes);
Gtk::TextView *textview = NULL;
refGlade->get_widget("textviewUser", textview);
assert(textview!=NULL);
textview->get_buffer()->set_text(str);
}
This function fires off when the file has been read and you can safely talk to the FileInputStream. Use the function of the parent of that class read_bytes, here i ask to read 8192 bytes, but it can potentially be more, the Cancellable reference must be provided, but can be empty as is the case above. Now the tricky part, grab the Glib::RefPtr<Glib::Bytes> and do the conversion with the function that had to be written for this:
Glib::ustring bytesToUstring(Glib::RefPtr<Glib::Bytes> data)
{
Glib::ustring result = "";
gsize s;
gconstpointer d = g_bytes_get_data(data->gobj(), &s);
unsigned char c;
wchar_t wc;
unsigned short toread = 0;
for(int i=0; i<(int)s; ++i)
{
c = ((char*)d)[i];
if((c >> 7) == 0b0)
{
//std::cout << "Byte 0b0" << std::endl;
if(toread!=0)
{
std::cerr << "Help. I lost my place in the stream" << std::endl;
}
wc = (wchar_t)c;
}
else if((c >> 6) == 0b10)
{
//std::cout << "Byte 0b10" << std::endl;
if(toread==0)
{
std::cerr << "Help. I lost my place in the stream" << std::endl;
}
wc <<= 6; // 6 more bits are coming in
wc |= (c & 0b00111111);
--toread;
}
else // we can be sure that we have something starting with at least 2 set bits
{
if(toread!=0)
{
std::cerr << "Help. I lost my place in the stream" << std::endl;
}
if((c >> 5) == 0b110)
{
//std::cout << "Byte 0b110" << std::endl;
wc = c & 0b00011111;
toread = 1;
}
else if((c >> 4) == 0b1110)
{
//std::cout << "Byte 0b1110" << std::endl;
wc = c & 0b00001111;
toread = 2;
}
else if((c >> 3) == 0b11110)
{
//std::cout << "Byte 0b11110" << std::endl;
wc = c & 0b00000111;
toread = 3;
}
else if((c >> 2) == 0b111110)
{
//std::cout << "Byte 0b111110" << std::endl;
wc = c & 0b00000011;
toread = 4;
}
else if((c >> 1) == 0b1111110)
{
//std::cout << "Byte 0b1111110" << std::endl;
wc = c & 0b00000001;
toread = 5;
}
else // wtf?
{
std::cerr << "Help! Something is probaby not a UTF-8 at all" << std::endl;
for(int j=(8*(int)sizeof c) - 1; j>=0; --j)
{
std::cerr << (char)('0'+ (char)((c >> j) & 1));
}
std::cerr << std::endl;
}
}
if(toread == 0)
{
result += (gunichar)wc;
wc = L'\0';
//std::cout << i << ' ' << result << std::endl;
}
}
return result;
}
In here we must first and foremost grab the real pointer to bytes, since Glib::Bytes will refuse to give you the tools that you need. And then you can start converting into the wchar_t. The process isn't that difficult and is described in Wikipedia article on UTF-8 well enough.
And luckily wchar_t can be converted to gunichar and that in turn can be added to Glib::ustring.
So the path that we must take is:
Dialog -> Gio::File -> Glib::Bytes -> gconstpointer -> char -> (combining several chars) wchar_t -> gunichar -> Glib::ustring -> (add to TextArea's TextBuffer)
:Note: Currently this is not a ready to use code, it only reads 8192 bytes, and it won't help to then read more because there is no guarantee that the character didn't get broken in the middle of two reads, maybe i'll update the code a little later.

If I have two instances of Glib::IOChannel, they block until both written. What is the correct way to do this?

I have modified the example found here to use two io channels. None of the callbacks seem to be called before I have written to both channels. After that they are called individually when writing to the fifos. Am I forgetting something?
Start the test program in one shell window.
Write echo "abc" > testfifo1 in second shell window. -> nothing happens.
Write echo "def" > testfifo2 in a third shell window. -> now I get "abc" and "def"
Write to one of the fifos. This is immediately served.
Edit:
The solution, as hinted by Gormley below, was the lack of nonblock.
read_fd1 = open("testfifo1", O_RDONLY | O_NONBLOCK);
...
read_fd2 = open("testfifo2", O_RDONLY | O_NONBLOCK);
This change to the code below made it respond immediately.
The code:
#include <gtkmm/main.h>
#include <fcntl.h>
#include <iostream>
int read_fd1, read_fd2;
Glib::RefPtr<Glib::IOChannel> iochannel1, iochannel2;
// Usage: "echo "Hello" > testfifo<1|2>", quit with "Q"
bool MyCallback1(Glib::IOCondition io_condition)
{
Glib::ustring buf;
iochannel1->read_line(buf);
std::cout << "io 1: " << buf;
if (buf == "Q\n")
Gtk::Main::quit();
return true;
}
bool MyCallback2(Glib::IOCondition io_condition)
{
Glib::ustring buf;
iochannel2->read_line(buf);
std::cout << "io 2: " << buf;
if (buf == "Q\n")
Gtk::Main::quit();
return true;
}
int main(int argc, char *argv[])
{
// the usual Gtk::Main object
Gtk::Main app(argc, argv);
if (access("testfifo1", F_OK) == -1)
{
if (mkfifo("testfifo1", 0666) != 0)
return -1;
}
if (access("testfifo2", F_OK) == -1)
{
if (mkfifo("testfifo2", 0666) != 0)
return -1;
}
read_fd1 = open("testfifo1", O_RDONLY);
if (read_fd1 == -1)
return -1;
read_fd2 = open("testfifo2", O_RDONLY);
if (read_fd2 == -1)
return -1;
Glib::signal_io().connect(sigc::ptr_fun(MyCallback1), read_fd1, Glib::IO_IN);
Glib::signal_io().connect(sigc::ptr_fun(MyCallback2), read_fd2, Glib::IO_IN);
iochannel1 = Glib::IOChannel::create_from_fd(read_fd1);
iochannel2 = Glib::IOChannel::create_from_fd(read_fd2);
app.run();
if (unlink("testfifo1"))
std::cerr << "error removing fifo 1" << std::endl;
if (unlink("testfifo2"))
std::cerr << "error removing fifo 2" << std::endl;
return 0;
}
These two statements block the program from getting into the main loop until both fifos
are open for write. fifos block until both sides are connected
iochannel1 = Glib::IOChannel::create_from_fd(read_fd1);
iochannel2 = Glib::IOChannel::create_from_fd(read_fd2);