How to implement a tcp server in GTK based application using GIOChannel - gtk3

I have got below sample from stackoverflow itself.
#include <glib.h>
#include <gio/gio.h>
gchar *buffer;
gboolean
network_write(GIOChannel *source,
GIOCondition cond,
gpointer data)
{
return TRUE;
}
gboolean
network_read(GIOChannel *source,
GIOCondition cond,
gpointer data)
{
GString *s = g_string_new(NULL);
GError *error;
g_print("Inside network_read function\n");
GIOStatus ret = g_io_channel_read_line_string(source, s, NULL, &error);
if (ret == G_IO_STATUS_ERROR)
g_error ("Error reading: %s\n", error->message);
else
g_print("Got: %s\n", s->str);
return TRUE;
}
gboolean
new_connection(GSocketService *service,
GSocketConnection *connection,
GObject *source_object,
gpointer user_data)
{
GSocketAddress *sockaddr = g_socket_connection_get_remote_address(connection, NULL);
GInetAddress *addr = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(sockaddr));
guint16 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(sockaddr));
g_print("New Connection from %s:%d\n", g_inet_address_to_string(addr), port);
GSocket *socket = g_socket_connection_get_socket(connection);
gint fd = g_socket_get_fd(socket);
g_print("Naseeb fd: %d\n", fd);
GIOChannel *channel = g_io_channel_unix_new(fd);
if(!g_io_add_watch(channel, G_IO_IN, (GIOFunc) network_read, NULL))
{
g_print("Got Error while adding network_read\n");
}
// g_io_add_watch(channel, G_IO_OUT, (GIOFunc) network_write, NULL);
return TRUE;
}
int main(int argc, char **argv) {
g_type_init();
GSocketService *service = g_socket_service_new();
GInetAddress *address = g_inet_address_new_from_string("0.0.0.0");
GSocketAddress *socket_address = g_inet_socket_address_new(address, 3001);
g_socket_listener_add_address(G_SOCKET_LISTENER(service), socket_address, G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP, NULL, NULL, NULL);
g_object_unref(socket_address);
g_object_unref(address);
g_socket_service_start(service);
g_signal_connect(service, "incoming", G_CALLBACK(new_connection), NULL);
g_socket_service_start(service);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
return 0;
}
Using this code, i am able to get the client connected to server. I confirm the same using message printed in the function new_connection
But when i send data from client, callback network_read never gets called at server. Although client side, send() API return value shows total bytes sent.
1) Is there any api missing at server side.
2) What is proper way to invoke network_write ?

You shouldn't be using GIOChannel, new_connection() already has a connection and you can just use stream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); to get a GInputStream to read from.

Related

Socket programming error, "Socket operation on non-socket"

This question has been asked many times, but searching through and implementing some solutions that have worked for others, I still haven't been able to figure out what I'm doing wrong. I am still having issues understanding programming with sockets, so any explanations would be greatly appreciated. The function where I am getting the error is "int forwardClientReq(char* buffer, char* hostname, int clientfd)" and more specifically around this:
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
if(numBytesSent == -1)
printf("Oh dear, something went wrong with send()! %s\n", strerror(errno));
The full code is as follows:
/* Proxy application called webproxy */
// Copy past http server includes, remove unnecessary
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for fgets */
#include <strings.h> /* for bzero, bcopy */
#include <unistd.h> /* for read, write */
#include <sys/socket.h> /* for socket use */
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#define MAXBUF 8192 /* max text line length */
#define LISTENQ 1024 /* second argument to listen() */
#define ERRBUFSIZE 1024
#define HEAPBUF 32768 // 2^15
int open_listenfd(int port);
void webProxy(int connfd);
void *thread(void *vargp);
int connect2Client(char* ip, char* port);
void sendErrResponse(char* errBUF, int connfd);
int forwardClientReq(char* buffer, char* host, int clientfd);
int main(int argc, char **argv)
{
int timeout = 0;
/* Check if the function was called correctly */
/* Store arguments provided (port number & cache timeout) */
if(argc < 2 || argc > 3){
fprintf(stderr, "Incorrect arguments, Usage: ./<executableFile> <port#> <timeout(optional)>\n");
exit(0);
}
if(argc == 3)
timeout = atoi(argv[2]);
int listenfd, *connfdp, port, clientlen=sizeof(struct sockaddr_in);
pthread_t tid;
struct sockaddr_in clientaddr;
port = atoi(argv[1]); // store the port number
listenfd = open_listenfd(port); // create persistant TCP socket for client HTTP requests
/* Create,Bind,Listen SOCKET and multithread */
while (1) {
connfdp = malloc(sizeof(int)); // pointer to pass the socket
*connfdp = accept(listenfd, (struct sockaddr*)&clientaddr, &clientlen);
if(*connfdp<0)
printf("There is an error accepting the connection with the client");
pthread_create(&tid, NULL, thread, connfdp); // call thread function with tid
}
}
/* thread routine */
void * thread(void * vargp)
{
int connfd = *((int *)vargp);
pthread_detach(pthread_self());
free(vargp);
webProxy(connfd);
close(connfd);
return NULL;
}
void webProxy(int connfd)
{
size_t n;
char buffer[MAXBUF]; // pointer to pass the socket
char errorBuf[ERRBUFSIZE];
bzero(errorBuf, ERRBUFSIZE);
bzero(buffer, MAXBUF);
char httpmsg[]="HTTP/1.1 200 Document Follows\r\nContent-Type:text/html\r\nContent-Length:32\r\n\r\n<html><h1>Hello CSCI4273 Course!</h1>";
char hostname[50];
n = read(connfd, buffer, MAXBUF); // read the requst up to maxbuf sizeof
printf("server received the following request:\n%s\n",buffer);
/* parse the request */
char requestType[50], fullPath[50];
bzero(requestType, 50);
bzero(fullPath, 50);
sscanf(buffer, "%s %s", requestType, fullPath);
printf("requestType = %s, and fullPath= %s\n", requestType, fullPath);
/* I tried a million different methods and libary suggestions but this is the only
method that I found to easily parse the information I wanted to input */
// sscanf(fullPath, "http://www.%511[^/\n]", hostname);
sscanf(fullPath, "http://%511[^/\n]", hostname);
printf("hostname is = %s\n", hostname);
/* support only GET requests */
if(strcmp(requestType, "GET") != 0)
{
printf("Proxy received a request that was not a 'GET' Request, sending 400 Bad Request response\n");
sendErrResponse(errorBuf, connfd);
}
// // /* support only HTTP/1.1 */
// else if(strcmp(Type, "HTTP/1.1") != 0)
// {
// printf("Proxy received a request that was not an HTTP/1.1 version, sending 400 Bad Request response");
// // I think the error message below is 80, but I could be wrong. Need to double check or use strlen function
// sprintf(errorBuf, "HTTP/1.1 400 Bad Request\r\nContent-Type:text/html\r\nContent-Length: %d\r\n\r\n",80);
// write(connfd, errorBuf, strlen(errorBuf));
// bzero(errorBuf, ERRBUFSIZE);
// }
/* parse and verify the hostname/server */
struct hostent *host = gethostbyname(hostname);
if (host == NULL) {
fprintf(stderr,"ERROR, no such host as %s\n", hostname);
sendErrResponse(errorBuf, connfd);
exit(0);
}
else{
/* Forward request to HTTP server */
forwardClientReq(buffer, hostname, connfd);
printf("buffer = %s\n", buffer);
/* Relay data from server to client */
}
}
int forwardClientReq(char* buffer, char* hostname, int clientfd)
{
char* serverResponse = malloc(HEAPBUF); // create a buffer for receiving the response from the server
bzero(serverResponse, HEAPBUF); // zeroize the buffer
/* open a socket with the server */
struct sockaddr_in serveraddr;
int serverSock, optval =1;
/* Create a socket descriptor */
if(-1 == (serverSock = socket(AF_INET, SOCK_STREAM, 0))) // yoda condition...
{
printf("Error: Unable to create socket in 'open_listenfd' function");
return -1;
}
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) < 0){
printf("Error in setsockopt in forwardClientReq function");
return -1;
}
struct hostent* host = gethostbyname(hostname);
serveraddr.sin_family = AF_INET;
memcpy(&serveraddr.sin_addr, host->h_addr_list[0], host->h_length);
serveraddr.sin_port = htons(80); //(you should pick the correct remote port or use the default 80 port if noneis specified).
socklen_t addrlen = sizeof(serveraddr); // The addrlen argument specifies the size of serveraddr.
int serverfd = connect(serverSock, (struct sockaddr*) &serveraddr, addrlen);
if(serverfd < 0)
printf("improper connection when trying to forward client's request/n");
/* send the client message to the server */
int numBytesSent = 0;
printf("buffer before send = %s\n", buffer);
sprintf(buffer, "\r\n\r\n");
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
if(numBytesSent == -1)
printf("Oh dear, something went wrong with send()! %s\n", strerror(errno));
// printf("Sent %d to the server", numBytesSent);
// /* store the server's response */
// int numBytesRead = 0;
// numBytesRead = read(serverfd, serverResponse, HEAPBUF);
// printf("Sent %d to the server", numBytesRead);
//
// /* send the response to the client. This is a moment here the proxy can cache the page,
// inspect the data, and do all kinds of cool proxy-level things */
// numBytesSent = write(clientfd, serverResponse, strlen(serverResponse));
// printf("Sent %d to the server", numBytesSent);
free(serverResponse); // free malloc'd space
}
int open_listenfd(int port)
{
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Error: Unable to create socket in 'open_listenfd' function");
return -1;
}
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) < 0)
return -1;
/* listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
/* bind: associate the parent socket with a port */
if (bind(listenfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
return listenfd;
} /* end open_listenfd */
void sendErrResponse(char* errorBuf, int connfd)
{
// I think the error message below is 80, but I could be wrong. Need to double check or use strlen function
sprintf(errorBuf, "HTTP/1.1 400 Bad Request\r\nContent-Type:text/html\r\nContent-Length: %d\r\n\r\n",80);
write(connfd, errorBuf, strlen(errorBuf));
bzero(errorBuf, ERRBUFSIZE);
}
The return value of connect is an error code not a socket fd:
If the connection or binding succeeds, zero is returned. On error,
-1 is returned, and errno is set appropriately.
So
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
Should be
numBytesSent = send(serverSock, buffer, strlen(buffer), 0);

I have a timing problem between read and write on a serial channel in gtk

This program is intended to communicate over an unreliable serial channel via a PL2303 usb converter with a distant microcontroller. The main loop uses g_io_add_watch to listen for data from the micro. It then calls g_io_read_chars to read the data and g_io_write_chars to send a one-byte acknowledge. The micro echos this back. The read and write are called from within ReadStationMessage. If the micro is slow to respond, the ReadStationMessage() function is called twice, once to read the data and again to receive the echo. However, if it responds immediately, ReadStationMessage() is called only once and the echo byte is appended to the data. I don't understand how this is possible when g_io_write_chars does not send the acknowledge until after g_io_read_chars returns and the micro does nothing until it receives the acknowledge.
#include <gtk/gtk.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
g_print("Error from tcgetattr: %s\n", strerror(errno));
return -1; }
cfmakeraw(&tty);
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
g_print("Error from tcsetattr: %s\n", strerror(errno));
return -1; }
return 0;
}
static gboolean ReadStationMessage( GIOChannel *channel, GIOCondition condition, guchar* user_data )
{
guchar buf[128];
gsize bytes_read, bytes_written;
gint i;
g_print("\nentering ReadStationMessage\n");
g_io_channel_read_chars( channel, buf, 128, &bytes_read, NULL );
for( i=0; i<bytes_read; i++ ) g_print("%u ", buf[i]);
buf[0] = 0;
g_io_channel_write_chars( channel, buf, 1, &bytes_written, NULL );
return TRUE;
}
int main( int argc, char *argv[] )
{
char *portname = "/dev/ttyUSB0";
gint fd;
GIOChannel *channel;
static guchar user_data[128];
GError *error=NULL;
guint EventSource_id;
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC );
set_interface_attribs(fd, B9600);
channel = g_io_channel_unix_new(fd);
g_io_channel_set_encoding(channel, NULL, &error); // raw data, no encoding
GIOCondition condition = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
gtk_init (&argc, &argv);
EventSource_id = g_io_add_watch( channel, condition, (GIOFunc) ReadStationMessage, user_data );
return 0;
}
Fixed! I need to g-io-channel-flush after write.

Trying to create a gsocket server with GUI program

I am trying to set up server that also has a gui using GTK on a Raspberry Pi. The program is just a proof-of-concept demo.
I create a socket and the client can connect and send data, I see it in wireshark. But the read does not complete until the client disconnects. My code uses g_data_input_stream_read_line_async and g_data_input_stream_read_line_finish. The program displays the data the client sent after the client disconnects.
Here is the output of the program (that is the correct data that was sent by the client).
g_socket_listener_add_inet_port status: 1
g_signal_connect status: 2 (waits here until client connects)
socket connection established!
after g_data_input_stream_new
after g_data_input_stream_set_newline_type
after g_data_input_stream_read_line_async (waits here after client connects, and after client sends data)
before g_data_input_stream_read_line_finish (displays remaining output lines after client disconnects)
after g_data_input_stream_read_line_finish
length: 14
0 5 0 4 0 1 0 1 0 6 0 0 0 7
I suspect I am missing something simple since the data is received, but I've spent quite a few hours unsuccessfully trying to figure out what is missing.
// compiles with:
// gcc `pkg-config --cflags gtk+-3.0` gtk3serv.c -o gtk3serv `pkg-config --libs gtk+-3.0`
#include <gtk/gtk.h>
#include <gio/gio.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
// v<>v<>v<>v<>v<>v<>v<>v<>v<>v<>v
static void on_input_read_finish(GObject *object,
GAsyncResult *result,
gpointer user_data)
{
gchar *clientdata;
gsize length = -1;
gsize i;
g_print("before g_data_input_stream_read_line_finish\n"); // only for debug
clientdata = g_data_input_stream_read_line_finish(G_DATA_INPUT_STREAM(object),
result,
&length,
NULL);
g_print("after g_data_input_stream_read_line_finish\n"); // only for debug
g_print("length: %d\n", length); // only for debug
for(i=0; i<length; i++)
{
g_print("%x ", clientdata[i]);
}
g_print("\n");
}
gboolean sockconnectionestablished(GSocketService *sockservice,
GSocketConnection *connection,
GObject *source_object,
gpointer user_Data)
{
char *clientdata;
gsize length = -1;
gsize i;
g_print("socket connection established!\n"); // only for debug
GDataInputStream *gis = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(connection)));
g_print("after g_data_input_stream_new\n"); // only for debug
g_data_input_stream_set_newline_type(G_DATA_INPUT_STREAM(gis), G_DATA_STREAM_NEWLINE_TYPE_ANY);
g_print("after g_data_input_stream_set_newline_type\n"); // only for debug
g_data_input_stream_read_line_async(G_DATA_INPUT_STREAM(gis),
G_PRIORITY_DEFAULT,
NULL,
on_input_read_finish,
NULL);
g_print("after g_data_input_stream_read_line_async\n"); // only for debug
return 1;
}
// ^<>^<>^<>^<>^<>^<>^<>^<>^<>^<>^
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
// v<>v<>v<>v<>v<>v<>v<>v<>v<>v<>v
GError *sockerror = NULL;
GSocketService *sockservice;
gboolean sockstatus;
sockservice = g_socket_service_new();
sockstatus = g_socket_listener_add_inet_port(G_SOCKET_LISTENER(sockservice),
8888,
NULL,
NULL);
g_print("g_socket_listener_add_inet_port status: %d\n", sockstatus); // only for debug
status = g_signal_connect(sockservice,
"incoming",
G_CALLBACK(sockconnectionestablished),
NULL);
g_print("g_signal_connect status: %d\n", status); // only for debug
// ^<>^<>^<>^<>^<>^<>^<>^<>^<>^<>^
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}

How to overlay a picture over a video stream with Gstreamer in C?

I want to overlay a ".png" picture over a stream coming from an IP Camera using Gstreamer.
A working pipeline for my hardware is:
gst-launch-1.0
rtspsrc location=rtsp://user:pass#IP:port/channel latency=400 ! rtph264depay !
vpudec use-vpu-memory=false ! imxvideoconvert_ipu
! video/x-raw,format=I420 ! gdkpixbufoverlay
location=/home/user/folder/image.png offset-x=100 offset-y=100 ! overlaysink
The problem comes when I try to translate this pipeline in C.
The code I wrote for this pipeline runs, but there is no video playback on the display. The player stuck itself before setting the pipeline on "playing" state.
Here, there is a simple version of my C implementation:
#include <gst/gst.h>
#include <glib.h>
#include <iostream>
typedef struct _CustomData {
GstElement *source;
GstElement *rtp;
GstElement *sink;
GstElement *vpudec;
GstElement *converter, *gdkpixbufoverlay, *capsfilter ;
GstBus *bus;
GstElement *pipeline;
GMainLoop *loop;
} CustomData;
static gboolean bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:{
g_print ("End of stream\n");
g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_ERROR: {
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {
GstPad *sink_pad = gst_element_get_static_pad (data->rtp, "sink");
GstPadLinkReturn ret;
GstCaps *new_pad_caps = NULL;
GstStructure *new_pad_struct = NULL;
const gchar *new_pad_type = NULL;
if (gst_pad_is_linked (sink_pad)) {
goto exit;
}
new_pad_caps = gst_pad_query_caps (new_pad, NULL);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "application/x-rtp")) {
g_print (" It has type '%s' which is not x-rtp . Ignoring.\n",
new_pad_type);
goto exit;
}
ret = gst_pad_link (new_pad, sink_pad);
if (GST_PAD_LINK_FAILED (ret)) {
g_print(" Type is '%s' but link failed.\n", new_pad_type);
} else {
g_print (" Link succeeded (type '%s').\n", new_pad_type);
}
exit:
if (new_pad_caps != NULL)
gst_caps_unref (new_pad_caps);
gst_object_unref (sink_pad);
}
int main (int argc, char *argv[]){
CustomData data;
gst_init (NULL, NULL);
data.loop = g_main_loop_new (NULL, FALSE);
// Create gstreamer elements
data.pipeline = gst_pipeline_new ("player");
data.source = gst_element_factory_make ("rtspsrc", "source");
data.rtp = gst_element_factory_make ("rtph264depay","rtp");
data.vpudec = gst_element_factory_make ("vpudec","vpudec");
data.converter = gst_element_factory_make
("imxcompositor_ipu","converter");
data.capsfilter = gst_element_factory_make ("capsfilter", "video-
rate");
data.gdkpixbufoverlay = gst_element_factory_make
("gdkpixbufoverlay","overlaytool");
data.sink = gst_element_factory_make ("overlaysink",
"videoSink");
if (!data.pipeline || !data.source || !data.rtp || !data.vpudec ||
!data.converter || !data.capsfilter || !data.gdkpixbufoverlay || !data.sink)
{
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
g_object_set (data.source, "location","rtsp://user:pass#IP:port/channel",
NULL);
g_object_set (data.source,"latency", 400 , NULL);
g_object_set (data.vpudec, "use-vpu-memory", false, NULL);
g_object_set (data.gdkpixbufoverlay,
"location","/home/user/folder/image.png", NULL);
g_object_set (data.gdkpixbufoverlay, "offset-x", 100 , NULL);
g_object_set (data.gdkpixbufoverlay, "offset-y", 100 , NULL);
GstCaps *capsFormat = gst_caps_from_string ("video/x-raw,format=I420");
g_object_set ( data.capsfilter, "caps", capsFormat, NULL);
gst_caps_unref(capsFormat);
//add all elements into the pipeline
gst_bin_add_many (GST_BIN (data.pipeline),
data.source,
data.rtp,
data.vpudec,
data.converter,
data.capsfilter,
data.gdkpixbufoverlay,
data.sink,
NULL);
// link all elements
gst_element_link_many ( data.rtp, data.vpudec , data.converter ,
data.capsfilter, data.gdkpixbufoverlay, data.sink, NULL);
g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler),
&data);
// Set the pipeline to "playing" state
GstStateChangeReturn ret;
ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr("Unable to set the pipeline to the playing state.\n");
gst_object_unref (data.pipeline);
return -1;
}
// Iterate
g_main_loop_run (data.loop);
// Out of the main loop, clean
g_print ("Returned, stopping playback\n");
gst_element_set_state (data.pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (data.pipeline));
return 0;
}
Does anyone see the problem?
Thank you
After many tries, I did figure out that in the C code I posted I have selected the wrong element, therefore the data.converter element is:
data.converter = gst_element_factory_make("imxvideoconvert_ipu ","converter");
and not imxcompositor_ipu .

GIO socket-server / -client example

I would like to create a server and client application that communicate via sockets using GIO. GSocketService and GSocketClient seem be perfect for this purpose but unfortunately I couldn't find some tutorial or example code (that a GLib, GIO,... newbie can understand). Does anybody know some good resources or can post example code here?
I finally managed to create both a simple server and client using glib and gio.
My server looks like this:
#include <glib.h>
#include <gio/gio.h>
/* this function will get called everytime a client attempts to connect */
gboolean
incoming_callback (GSocketService *service,
GSocketConnection *connection,
GObject *source_object,
gpointer user_data)
{
g_print("Received Connection from client!\n");
GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
gchar message[1024];
g_input_stream_read (istream,
message,
1024,
NULL,
NULL);
g_print("Message was: \"%s\"\n", message);
return FALSE;
}
int
main (int argc, char **argv)
{
/* initialize glib */
g_type_init();
GError * error = NULL;
/* create the new socketservice */
GSocketService * service = g_socket_service_new ();
/* connect to the port */
g_socket_listener_add_inet_port ((GSocketListener*)service,
1500, /* your port goes here */
NULL,
&error);
/* don't forget to check for errors */
if (error != NULL)
{
g_error (error->message);
}
/* listen to the 'incoming' signal */
g_signal_connect (service,
"incoming",
G_CALLBACK (incoming_callback),
NULL);
/* start the socket service */
g_socket_service_start (service);
/* enter mainloop */
g_print ("Waiting for client!\n");
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
return 0;
}
and this is the corresponding client:
#include <glib.h>
#include <gio/gio.h>
int
main (int argc, char *argv[])
{
/* initialize glib */
g_type_init ();
GError * error = NULL;
/* create a new connection */
GSocketConnection * connection = NULL;
GSocketClient * client = g_socket_client_new();
/* connect to the host */
connection = g_socket_client_connect_to_host (client,
(gchar*)"localhost",
1500, /* your port goes here */
NULL,
&error);
/* don't forget to check for errors */
if (error != NULL)
{
g_error (error->message);
}
else
{
g_print ("Connection successful!\n");
}
/* use the connection */
GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
GOutputStream * ostream = g_io_stream_get_output_stream (G_IO_STREAM (connection));
g_output_stream_write (ostream,
"Hello server!", /* your message goes here */
13, /* length of your message */
NULL,
&error);
/* don't forget to check for errors */
if (error != NULL)
{
g_error (error->message);
}
return 0;
}
Note though, that I am still new to glib, gio and even C, so double check my code before using it.
The callback from incoming should not block, from gio documentation: "The handler must initiate the handling of connection , but may not block; in essence, asynchronous operations must be used."
I had some issue with connection in the async version, it has to be referred by the user or the connection will close after the incoming callback returns.
A full example of a server that does not block, based on the example given before:
#include <gio/gio.h>
#include <glib.h>
#define BLOCK_SIZE 1024
#define PORT 2345
struct ConnData {
GSocketConnection *connection;
char message[BLOCK_SIZE];
};
void message_ready (GObject * source_object,
GAsyncResult *res,
gpointer user_data)
{
GInputStream *istream = G_INPUT_STREAM (source_object);
GError *error = NULL;
struct ConnData *data = user_data;
int count;
count = g_input_stream_read_finish (istream,
res,
&error);
if (count == -1) {
g_error ("Error when receiving message");
if (error != NULL) {
g_error ("%s", error->message);
g_clear_error (&error);
}
}
g_message ("Message was: \"%s\"\n", data->message);
g_object_unref (G_SOCKET_CONNECTION (data->connection));
g_free (data);
}
static gboolean
incoming_callback (GSocketService *service,
GSocketConnection * connection,
GObject * source_object,
gpointer user_data)
{
g_message ("Received Connection from client!\n");
GInputStream *istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
struct ConnData *data = g_new (struct ConnData, 1);
data->connection = g_object_ref (connection);
g_input_stream_read_async (istream,
data->message,
sizeof (data->message),
G_PRIORITY_DEFAULT,
NULL,
message_ready,
data);
return FALSE;
}
int main ()
{
GSocketService *service;
GError *error = NULL;
gboolean ret;
service = g_socket_service_new ();
ret = g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service),
PORT, NULL, &error);
if (ret && error != NULL)
{
g_error ("%s", error->message);
g_clear_error (&error);
return 1;
}
g_signal_connect (service,
"incoming",
G_CALLBACK (incoming_callback),
NULL);
g_socket_service_start (service);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
/* Stop service when out of the main loop*/
g_socket_service_stop (service);
return 0;
}