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

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);

Related

I'm converting ints to chars and trying to send them from a C client to a Python server on another computer. Getting 'send: Bad address'

On one computer with the client (written in C) I get the error send: Bad address when I try to send chars to another computer with a server written in Python. But the address is NOT bad.
If instead of chars I just send a written string, "A string written like this" I can send it just fine to the server and see it print with no problems. So, I don't think there is really a problem with an address.
I have also tried converting the int to a string. I get error when compiling cannot convert string to char. I have tried variations and I can only compile with the client written as it is below.
The client (in C)
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#define ADDR "192.168.0.112"
#define PORT "12003"
void sendall(int socket, char *bytes, int length)
{
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
if (n == -1) {
perror("send");
exit(1);
}
total += n;
}
}
void thesock(char *ADDRf, char *PORTf, char *RAZZstr)
{
struct addrinfo hints = {0}, *addr = NULL;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status = getaddrinfo(ADDRf, PORTf, &hints, &addr);
if (status != 0) {
std::cerr << "Error message";
exit(1);
}
int sock = -1;
struct addrinfo *p = NULL;
for (p = addr; p != NULL; p = addr->ai_next) {
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sock == -1) {
continue;
}
if (connect(sock, p->ai_addr, p->ai_addrlen) != -1) {
break;
}
close(sock);
}
if (p == NULL) {
fprintf(stderr, "connect(), socket()\n");
exit(1);
}
sendall(sock, RAZZstr, 12);
close(sock);
}
int main()
{
int someInt = 321;
char strss[12];
sprintf(strss, "%d", someInt);
thesock(ADDR, PORT, strss);
return 0;
}
This last part of the code above is where the chars, or string is entered. It's this part of the code where you can replace strss in thesock with a string written in the strss position "just like this" and it will send to the server on the other computer written in Python. Though, when compiling I do get warnings ISO C++ forbids converting a string constant to ‘char*’.
The server (In Python)
import os
import sys
import socket
s=socket.socket()
host='192.168.0.112'
port=12003
s.bind((host,port))
s.listen(11)
while True:
c, addr=s.accept()
content=c.recv(29).decode('utf-8')
print(content)
This server decodes utf-8. I don't know if I have the option for a different 'decode' here. I don't think Python has 'chars'.
TL;DR: this is unrelated to "address" in terms of IP address but it is about invalid access to a local memory access.
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
total - length is a negative number, i.e. 0-12 = -12 in your case. The third argument of send is of type size_t, i.e. an unsigned integer. The negative number (-12) thus gets cast into an unsigned integer, resulting in a huge unsigned integer.
This causes send to access memory far outside the allocated memory for bytes, hence EFAULT "Bad address".

Getting information about process in Swift

I am trying to get some data about a process in Swift.
I am using this code as a starting point:
pid_t pid = 10000;
rusage_info_current rusage;
if (proc_pid_rusage(pid, RUSAGE_INFO_CURRENT, (void **)&rusage) == 0)
{
cout << rusage.ri_diskio_bytesread << endl;
cout << rusage.ri_diskio_byteswritten << endl;
}
taken from Per Process disk read/write statistics in Mac OS X.
However, I have trouble converting the code above to Swift:
var usage = rusage_info_v3()
if proc_pid_rusage(100, RUSAGE_INFO_CURRENT, &usage) == 0
{
Swift.print("Success")
}
The function prod_pid_rusage expects a parameter of type rusage_info_t?, but I can not instantiate an instance of that type.
Is it possible to use the function in Swift?
Regards,
Sascha
As in C you have to take the address of a rusage_info_current
variable and cast it to the type expected by proc_pid_rusage().
In Swift this is done using withUnsafeMutablePointer()
and withMemoryRebound():
let pid = getpid()
var usage = rusage_info_current()
let result = withUnsafeMutablePointer(to: &usage) {
$0.withMemoryRebound(to: rusage_info_t?.self, capacity: 1) {
proc_pid_rusage(pid, RUSAGE_INFO_CURRENT, $0)
}
}
if result == 0 {
print(usage.ri_diskio_bytesread)
// ...
}
You have to add
#include <libproc.h>
to the bridging header file to make it compile.

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.

How to use getaddrinfo()?

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);
}
}