Shared object library usage in gambas - c

I need to use mqtt protocol in gambas to get jobs done.
I used mosquitto api and mosquitto-dev library then created something like that:
`
#include <stdio.h>
#include <mosquitto.h>
int connectt(char *mqname,bool mqbool){
printf("something happens...1");
int rc;
struct mosquitto * mosq;
mosquitto_lib_init();
mosq=mosquitto_new(mqname,mqbool,NULL);
mosquitto_connect(mosq,"localhost",1883,60);
if(rc!=0){
printf("i cant connect to broker");
mosquitto_destroy(mosq);
return -1;
}else if(rc==0){
printf("Connected to broker yeey");
return 0;
}
mosquitto_publish(mosq,NULL,"targe/test",6,"Yeey",0,false);
mosquitto_disconnect(mosq);
printf("something happening...2");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
printf("something happening...3");
return 0;
int main(){
connectt("tester",true);
}
and i created shared object file with this way:
1gcc -c -g mosquit.c -lmosquitto
gcc -shared -o libmosquit.so mosquit.o
gcc -Llib/ -Wall -o targele mosquit.c -lmosquitto
so i moved libmosquit.so file to /lib/x86_64-linux-gnu/ directory
Untill here everything is fine, when i run targele it send "Yeeyt" payload but when i try it in gambas with these lines
`
Library "libmosquit"
Extern connectt(mqname As String, mqbool As Boolean) As Integer
Public Sub Main()
connectt("tester", True)
End
`
it says connection estabilished but do not send payload.
I tried directy importing library from mosquitto api but i couldn't figure out gambas structures and i don't need all of those functions

Your code returns if rc != 0 or rc == 0 (i.e. in all cases) meaning the call to mosquitto_publish is never reached. In your case rc is never set, you define it (int rc), but do not assign anything to it i.e. rc = mosquitto_connect(mosq, "test.mosquitto.org", 1883, 60); so effectively your code is:
int rc
if (rc != 0) {
printf("i cant connect to broker");
mosquitto_destroy(mosq);
return -1;
} else if (rc == 0) {
printf("Connected to broker yeey");
return 0;
}
// Any code below here is unreachable
When you have fixed that you may run into another issue; you might find this example useful. mosquitto_connect "makes the socket connection only, it does not complete the MQTTCONNECT/CONNACK flow, you should use mosquitto_loop_start() or mosquitto_loop_forever() for processing net traffic".

Related

How to ping /dev/watchdog from 2 processes?

In Linux (running on ARM) there is one process that has an open fd to /dev/watchdog/ and is sending an ioctl() each few seconds as a keep alive:
while (1) {
ioctl(fd, WDIOC_KEEPALIVE, 0);
sleep(10);
}
I want to send the keep alive from another process too, but I can't open another fd to /dev/watchdog/: when I tried to echo to /dev/watchdog/ I get the error "Device or resource busy".
Where I can see that the watchdog is defined to work only with 1 process at a time? (I saw in another Linux that some processes can open fd to /dev/watchdog/).
What can I do to feed the watchdog from 2 processes?
Due to the implementation of /dev/watchdog in the kernel, only one process can use it at the same time, so opening /dev/watchdog from two different processes is not possible.
You can see this right in the source code of the Linux kernel, specifically in drivers/watchdog/watchdog_dev.c. Here's the relevant snippet of code:
/*
* watchdog_open: open the /dev/watchdog* devices.
* #inode: inode of device
* #file: file handle to device
*
* When the /dev/watchdog* device gets opened, we start the watchdog.
* Watch out: the /dev/watchdog device is single open, so we make sure
* it can only be opened once.
*/
static int watchdog_open(struct inode *inode, struct file *file)
{
/* ... */
/* the watchdog is single open! */
if (test_and_set_bit(_WDOG_DEV_OPEN, &wd_data->status))
return -EBUSY;
/* ... */
If you want to feed the watchdog from two different processes, you can work around this issue by creating a simple "master" program that talks to the watchdog while orchestrating the two subprocesses as you wish. This can be done in different ways (pipes, sockets, threads, etc). A single popen() per child process seems like a simple solution.
Here's a working example, master.c:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>
int main(int argc, char **argv) {
int watchdog_fd;
FILE *child1_fp, *child2_fp;
if (argc != 3 || !argv[1] || !*argv[1] || !argv[2] || !*argv[2]) {
fprintf(stderr, "Usage: %s 'CHILD_1_COMMAND' 'CHILD_2_COMMAND'\n", argv[0]);
return 1;
}
// Open a fd to talk to the watchdog.
watchdog_fd = open("/dev/watchdog", O_RDWR);
if (watchdog_fd == -1) {
perror("open failed");
return 1;
}
// Start the first process.
child1_fp = popen(argv[1], "r");
if (child1_fp == NULL) {
perror("popen (1) failed");
return 1;
}
// Start the second process.
child2_fp = popen(argv[2], "r");
if (child2_fp == NULL) {
perror("popen (2) failed");
return 1;
}
while (1) {
char tmp;
size_t count;
// Get one byte of data from each of the two processes.
count = fread(&tmp, 1, 1, child1_fp);
count += fread(&tmp, 1, 1, child2_fp);
// If both processes provided the data, ping the watchdog.
if (count == 2) {
if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
perror("ioctl failed");
}
}
return 0;
}
And two identical programs a.c and b.c just for testing purposes:
#include <stdio.h>
#include <unistd.h>
int main(void) {
setvbuf(stdout, NULL, _IONBF, 0);
while (1) {
putchar('x');
sleep(10);
}
}
Compile and run:
$ gcc -o master master.c
$ gcc -o a a.c
$ gcc -o b b.c
$ ./master ./a ./b
In the above example code, master pings the watchdog if and only if the two children are alive and running: if one of the two hangs or dies, the master will stop pinging the watchdog. However, it's simple to rework the logic to work differently, and it's also simple to make it work with more than two child processes.

Network diagnostics for ZeroMQ Example

I am trying to implement ZeroMQ to get an application on a Raspberry Pi 3 (Raspbian Stretch) to communicate with an application on a separate machine (in this case Windows 7 64bit OS) linked by a wired or WLAN connection.
I have compiled ZeroMQ with the C library interface on both machines (using Cygwin on Windows) and the Hello World example (which I modified slightly to print the pointer values to assure me that the functions were 'working'). Both machines are connected (in this case via a wired Ethernet link and a router) and the connection is good (I link to RPi from PC via Xrdp or SSH OK).
The problem I have is that the client/server ZeroMQ programs don't appear to be 'seeing' each other even though they do appear to work and my question is: What are the first steps I should take to investigate why this is happening? Are there any commandline or GUI tools that can help me find out what's causing the blockage? (like port activity monitors or something?).
I know very little about networking so consider me a novice in all things sockety/servicey in your reply. The source code on the RPi (server) is:
// ZeroMQ Test Server
// Compile with
// gcc -o zserver zserver.c -lzmq
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
void *context=NULL,*responder=NULL;
int rc=1;
// Socket to talk to clients
context = zmq_ctx_new ();
printf("Context pointer = %p\n",context);
responder = zmq_socket (context, ZMQ_REP);
printf("Responder pointer = %p\n",responder);
rc = zmq_bind (responder, "tcp://*:5555");
printf("rc = %d\n",rc);
assert (rc == 0);
while (1) {
char buffer [10];
zmq_recv (responder, buffer, 10, 0);
printf ("Received Hello\n");
sleep (1); // Do some 'work'
zmq_send (responder, "World", 5, 0);
}
return 0;
}
The source code on the PC (Cygwin) client is:
// ZeroMQ Test Client
// Compile with:
// gcc -o zclient zclient.c -L/usr/local/lib -lzmq
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main (void)
{
void *context=NULL,*requester=NULL;
printf ("Connecting to hello world server\n");
context = zmq_ctx_new ();
printf("Context pointer = %p\n",context);
requester = zmq_socket (context, ZMQ_REQ);
printf("Requester pointer = %p\n",requester);
zmq_connect (requester, "tcp://localhost:5555");
int request_nbr;
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
char buffer [10];
printf ("Sending Hello %d\n", request_nbr);
zmq_send (requester, "Hello", 5, 0);
zmq_recv (requester, buffer, 10, 0);
printf ("Received World %d\n", request_nbr);
}
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
On the RPi LXTerminal I run the server and get this:
Context pointer = 0xefe308
Responder pointer = 0xf00e08
rc = 0
and on the Cygwin Bash shell I run the client and get this:
Connecting to hello world server
Context pointer = 0x60005ab90
Requester pointer = 0x60005f890
Sending Hello 0
... and there they both hang - one listening, the other sending but neither responding to each other.
Any clue how to start investigating this would be appreciated.
+1 for a care using explicit zmq_close() and zmq_ctx_term() release of resources ...
In case this is the first time to work with ZeroMQ,
one may here enjoy to first look at "ZeroMQ Principles in less than Five Seconds" before diving into further details
Q : What are the first steps I should take to investigate why this is happening?
A Line-of-Sight test as a step zero makes no sense here.
All localhost-placed interfaces are hard to not "see" one another.
Next, test as a first step call { .bind() | .connect() }-methods using an explicit address like tcp://127.0.0.1:56789 ( so as to avoid the expansion of both the *-wildcard and the localhost-symbolic name translations )
Always be ready to read/evaluate the API-provided errno that ZeroMQ keeps reporting about the last ZeroMQ API-operation resultin error-state.
Best read the ZeroMQ native API documentation, which is well maintained from version to version, so as to fully understand the comfort of API designed signaling/messaging meta-plane.
Mea Culpa: the LoS is sure not to have been established by the O/P code:
RPi .bind()-s on it's local I/F ( and cannot otherwise )
PC .connect()-s not to that of RPi, but the PC's local I/F
PC .connect( "tcp://<address_of_RPi>:5555" ) will make it ( use the same IP-address as you use in Xrdp or SSH to connect to RPi or may read one explicitly from RPi CLI-terminal after ~$ ip address and use that one for PC-side client code )
Two disjoint ZeroMQ AccessPoint-s have zero way how to communicate,once no transport-"wire" from A to B
// Zero MQ Test Server
// Compile with
// gcc -o zserver zserver.c -lzmq
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
void *context=NULL,*responder=NULL;
int rc=1;
// Socket to talk to clients
context = zmq_ctx_new (); printf("Context pointer = %p\n",context);
responder = zmq_socket (context, ZMQ_REP); printf("Responder pointer = %p\n",responder);
rc = zmq_bind (responder, "tcp://*:5555"); printf("rc = %d\n",rc);
/* ----------------------------------^^^^^^------------RPi interface-----------*/
assert (rc == 0);
while (1) {
char buffer [10];
zmq_recv (responder, buffer, 10, 0); printf("Received Hello\n");
sleep (1); // Do some 'work'
zmq_send (responder, "World", 5, 0);
}
return 0;
}
The source code on the PC (Cygwin) client is:
// ZeroMQ Test Client
// Compile with:
// gcc -o zclient zclient.c -L/usr/local/lib -lzmq
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main (void)
{
void *context=NULL,*requester=NULL;
printf("Connecting to hello world server\n");
context = zmq_ctx_new (); printf("Context pointer = %p\n",context);
requester = zmq_socket (context, ZMQ_REQ); printf("Requester pointer = %p\n",requester);
zmq_connect (requester, "tcp://localhost:5555");
/*---------------------------------^^^^^^^^^^^^^^---------PC-local-interface------*/
int request_nbr;
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
char buffer [10]; printf("Sending Hello %d\n", request_nbr);
zmq_send (requester, "Hello", 5, 0);
zmq_recv (requester, buffer, 10, 0); printf("Received World %d\n", request_nbr);
}
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
May like to also read more on ZeroMQ-related subjects here
Epilogue :
The trouble reported in the O/P is actually masked and remains hidden from being detectable by the API. ZeroMQ permits one AccessPoint to have 0+ transport-class-connections simultaneously, given a proper syntax and other conditions are met.
A call tozmq_connect( reguester, "tcp://<address-not-intended-but-correct>:<legal-port>" ) will result in legally-fair state and none of the defined and documented cases of possible error-states would get reported, because none of all such cases did actually happen:
EINVAL
The endpoint supplied is invalid.
EPROTONOSUPPORT
The requested transport protocol is not supported.
ENOCOMPATPROTO
The requested transport protocol is not compatible with the socket type.
ETERM
The ØMQ context associated with the specified socket was terminated.
ENOTSOCK
The provided socket was invalid.
EMTHREAD
No I/O thread is available to accomplish the task.
There are some chances to at least somehow-"detect" the trouble would be to enforce another sort of exception/error, but deferred into the call of { zmq_recv() | zmq_recv() } in their non-blocking form, where these may turn into reporting EAGAIN or might be EFSM for not having completed the end-to-end re-confirmed ZMTP-protocol handshaking ( no counterparty was and would never be met on the PC-localhost-port with remote RPi-server-side ). This requires also prior settings of zmq_setsockopt( responder, ZMQ_IMMEDIATE, 1 ) and other configuration details.
Next one, in ZeroMQ v4.+, there is a chance to inspect a subset of AccessPoint's internally reported events, using an "inspection-socket" via a rather complex strategy of instantiatingint zmq_socket_monitor (void *socket, char *endpoint, int events); attached to the AccessPoint's internals via inproc:// transport-class ~ here "inproc://myPCsocketAccessPOINT_monitor" like this:
rc = zmq_socket_monitor( responder, // AccessPoint to monitor
"inproc://myPCsocketAccessPOINT_monitor", // symbolinc name
ZMQ_ALL_EVENTS // scope of Events
);
Such created internal monitoring "inspection-socket" may next get zmq_connect()-ed to like:
void *my_end_of_monitor_socket = zmq_socket ( context, ZMQ_PAIR );
rc = zmq_connect( my_end_of_monitor_socket, // local-end PAIR-socket AccessPoint
"inproc://myPCsocketAccessPOINT_monitor" // symbolic name
);
and finally, we can use this to read a sequence of events (and act accordingly ):
int event = get_monitor_event( my_end_of_monitor_socket, NULL, NULL );
if (event == ZMQ_EVENT_CONNECT_DELAYED) { ...; }
if (event == ... ) { ...; }
using as a tool a trivialised get_monitor_event() like this, that handles some of the internal rules of reading and interpreting the multi-part messages that come as ordered from the instantiated "internal"-monitor attached to the AccessPoint:
// Read one event off the monitor socket; return value and address
// by reference, if not null, and event number by value. Returns -1
// in case of error.
static int
get_monitor_event ( void *monitor, int *value, char **address )
{
// First frame in message contains event number and value
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor, 0) == -1) return -1; // Interrupted, presumably
assert (zmq_msg_more (&msg));
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
uint16_t event = *(uint16_t *) (data);
if (value) *value = *(uint32_t *) (data + 2);
// Second frame in message contains event address
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor, 0) == -1) return -1; // Interrupted, presumably
assert (!zmq_msg_more (&msg));
if (address) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*address = (char *) malloc (size + 1);
memcpy (*address, data, size);
(*address)[size] = 0;
}
return event;
}
What internal-API-events can be monitored ?
As of the state of v4.2 API, there is this set of "internal"-monitor(able) internal-API-events:
ZMQ_EVENT_CONNECTED
The socket has successfully connected to a remote peer. The event value is the file descriptor (FD) of the underlying network socket. Warning: there is no guarantee that the FD is still valid by the time your code receives this event.
ZMQ_EVENT_CONNECT_DELAYED
A connect request on the socket is pending. The event value is unspecified.
ZMQ_EVENT_CONNECT_RETRIED
A connect request failed, and is now being retried. The event value is the reconnect interval in milliseconds. Note that the reconnect interval is recalculated at each retry.
ZMQ_EVENT_LISTENING
The socket was successfully bound to a network interface. The event value is the FD of the underlying network socket. Warning: there is no guarantee that the FD is still valid by the time your code receives this event.
ZMQ_EVENT_BIND_FAILED
The socket could not bind to a given interface. The event value is the errno generated by the system bind call.
ZMQ_EVENT_ACCEPTED
The socket has accepted a connection from a remote peer. The event value is the FD of the underlying network socket. Warning: there is no guarantee that the FD is still valid by the time your code receives this event.
ZMQ_EVENT_ACCEPT_FAILED
The socket has rejected a connection from a remote peer. The event value is the errno generated by the accept call.
ZMQ_EVENT_CLOSED
The socket was closed. The event value is the FD of the (now closed) network socket.
ZMQ_EVENT_CLOSE_FAILED
The socket close failed. The event value is the errno returned by the system call. Note that this event occurs only on IPC transports.
ZMQ_EVENT_DISCONNECTED
The socket was disconnected unexpectedly. The event value is the FD of the underlying network socket. Warning: this socket will be closed.
ZMQ_EVENT_MONITOR_STOPPED
Monitoring on this socket ended.
ZMQ_EVENT_HANDSHAKE_FAILED
The ZMTP security mechanism handshake failed. The event value is unspecified.
NOTE: in DRAFT state, not yet available in stable releases.
ZMQ_EVENT_HANDSHAKE_SUCCEED
NOTE: as new events are added, the catch-all value will start returning them. An application that relies on a strict and fixed sequence of events must not use ZMQ_EVENT_ALL in order to guarantee compatibility with future versions.
Each event is sent as two frames. The first frame contains an event number (16 bits), and an event value (32 bits) that provides additional data according to the event number. The second frame contains a string that specifies the affected TCP or IPC endpoint.
In zmq_connect, you must indicate the IP address of the raspberry (which have executed zmq_bind:
It should have been:
// on PC, remote ip is the raspberry one, the one you use for ssh for instance
rc = zmq_connect(requester, "tcp://<remote ip>:5555");

Weird recursive behavior using XCB

I'm exploring creating a window manager using XCB, but I've run into some troubles pretty early on. My code won't even connect to XCB with xcb_connect. I thought it was pretty straightforward, but I'm getting some really strange behavior. My code looks like this:
#include <stdio.h>
#include <xcb/xcb.h>
int i = 0;
int connect(xcb_connection_t** conn) {
xcb_connection_t* try_conn = xcb_connect(NULL, NULL);
int status = 0;
int conn_status = xcb_connection_has_error(try_conn);
if (conn_status != 0) {
i = i + 1;
switch (conn_status) {
case XCB_CONN_ERROR:
printf("Error connecting to the X Server, try %d\n", i);
break;
case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
printf("Connection closed, extension not supported\n");
break;
case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
printf("Connection closed, memory insufficient\n");
break;
case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
printf("Connection closed, required length exceeded\n");
break;
case XCB_CONN_CLOSED_PARSE_ERR:
printf("Connection closed, parse error\n");
break;
case XCB_CONN_CLOSED_INVALID_SCREEN:
printf("Connection closed, invalid screen\n");
break;
default:
printf("Connection failed with unknown cause\n");
break;
}
status = 1;
} else {
*conn = try_conn;
status = 0;
}
return status;
}
int main() {
xcb_connection_t* conn = NULL;
if (connect(&conn) != 0) {
printf("Error connecting to the X Server\n");
return -1;
}
return 0;
}
It prints the line that says Error connecting the the X Server, try %d\n 8191 times every time I run the program. When I looked at what was going on with gdb, it seems like every time I call xcb_connect, my code goes into this deep recursion thing (like thousands of frames deep) between xcb_connect_to_display_with_auth_info() and my connect() function.
The part that really confuses me is how xcb_connect_to_display_with_auth_info() can even call my connect() function at all, because it's from a separate library and I haven't passed in a pointer to my function. My code looks to me like it's behavior should be completely "linear", but that's not the case at all.
I'm testing the window manager by running Xephyr with the X server name :1 and setting DISPLAY to :1 before running the program.
I'm somewhat new to XCB and C itself, so I'm probably missing something blatantly obvious, but I would appreciate any pointers. I've been looking at hootwm for inspiration mostly so far.
You are overriding the C library's connect function. XCB calls that function to connect to the X11 server, but instead ends up with calling your function instead.
https://linux.die.net/man/2/connect
One possible way out of this (besides giving your function another name) is to make it static.

Function called from external .c file does nothing

I am trying to setup a function for a mosquitto pub command. This command is held in a separate .c file from the main .c file. Everything compiles fine but when I call the function (called within the external .c file) from within the external .c file nothing happens. Conversely if I invoke the function in it's own compiled program with no external .c file, the function acts as it should. Realizing that I am doing something wrong, I tried to do something simple by a simple printf function and calling it in the external .c file and it compiles fine but still doesn't print my data. What am I doing wrong? I have the function defined in the .h also.
void mosquittoto(void)
{
struct mosquitto *mosq = NULL;
// Initialize the Mosquitto library
mosquitto_lib_init();
// Create a new Mosquitto runtime instance with a random client ID,
// and no application-specific callback data.
mosq = mosquitto_new (NULL, true, NULL);
if (!mosq)
{
fprintf (stderr, "Can't initialize Mosquitto library\n");
exit (-1);
}
mosquitto_username_pw_set (mosq, MQTT_USERNAME, MQTT_PASSWORD);
// Establish a connection to the MQTT server. Do not use a keep-alive ping
int ret = mosquitto_connect (mosq, MQTT_HOSTNAME, MQTT_PORT, 0);
if (ret)
{
fprintf (stderr, "Can't connect to Mosquitto server\n");
exit (-1);
}
int i;
char text[20];
for (i = 0; i < 10; i++)
{
//sprintf (text, "Hello, World %d", i);
// Publish the message to the topic
ret = mosquitto_publish (mosq, NULL, MQTT_TOPIC,
strlen (epc4pub), epc4pub, 0, false);
if (ret)
{
fprintf (stderr, "Can't publish to Mosquitto server\n");
exit (-1);
}
}
// We need a short delay here, to prevent the Mosquitto library being
// torn down by the operating system before all the network operations
// are finished.
sleep (1);
// Tidy up
mosquitto_disconnect (mosq);
mosquitto_destroy (mosq);
mosquitto_lib_cleanup();
}
I have the function defined in the .h file as:
void mosquittoto(void);
Thank you all for your help!

How to create a simple Proxy to access web servers in C

I’m trying to create an small Web Proxy in C. First, I’m trying to get a webpage, sending a GET frame to the server.
I don’t know what I have missed, but I am not receiving any response. I would really appreciate if you can help me to find what is missing in this code.
int main (int argc, char** argv) {
int cache_size, //size of the cache in KiB
port,
port_google = 80,
dir,
mySocket,
socket_google;
char google[] = "www.google.es", ip[16];
struct sockaddr_in socketAddr;
char buffer[10000000];
if (GetParameters(argc,argv,&cache_size,&port) != 0)
return -1;
GetIP (google, ip);
printf("ip2 = %s\n",ip);
dir = inet_addr (ip);
printf("ip3 = %i\n",dir);
/* Creation of a socket with Google */
socket_google = conectClient (port_google, dir, &socketAddr);
if (socket_google < 0) return -1;
else printf("Socket created\n");
sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, MESSAGE_LENGTH+1) < 0 )
return 1;
else printf("GET frame sent\n");
strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));
// strcpy(message,buffer);
printf("%s\n", buffer);
return 0;
}
And this is the code I use to create the socket. I think this part is OK, but I copy it just in case.
int conectClient (int puerto, int direccion, struct sockaddr_in *socketAddr) {
int mySocket;
char error[1000];
if ( (mySocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("Error when creating the socket\n");
return -2;
}
socketAddr->sin_family = AF_INET;
socketAddr->sin_addr.s_addr = direccion;
socketAddr->sin_port = htons(puerto);
if (connect (mySocket, (struct sockaddr *)socketAddr,sizeof (*socketAddr)) == -1) {
snprintf(error, sizeof(error), "Error in %s:%d\n", __FILE__, __LINE__);
perror(error);
printf("%s\n",error);
printf ("-- Error when stablishing a connection\n");
return -1;
}
return mySocket;
}
Thanks!
First, you're not checking how many bytes the write(2) call actually wrote to the socket. The return value of the call tells you that. Same for the read(2). TCP socket is a bi-directional stream, so as a rule always do both in a loop until expected number of bytes is transferred, EOF is read (zero return from read(2)), or an error occurred (which you are not checking for when reading either).
Then HTTP is rather complex protocol. Make yourself familiar with RFC 2616, especially application level connection management and transfer encodings.
Edit 0:
Hmm, there's no such thing as "simple" proxy. You need to manage multiple connections (at least client-to-proxy and proxy-to-server), so it's probably best to look into select(2)/poll(2)/epoll(4)/kqueue(2) family of system call, which allow you to multiplex I/O. This is usually combined with non-blocking sockets. Look into helper libraries like libevent. Look at how this is done in good web-servers/proxies like nginx. Sound like it's a lot for you to discover, but don't worry, it's fun :)
Since you didn't post the GetIP routine, I am not certain that your hostname lookup is correct, as from the looks of it, I am not sure that you are using inet_addr function correctly.
Nikolai has pointed out some very good points (and I fully agree). In fact you GET request is actually broken, and while I was testing it on my own local Apache web server on my system, it didn't work.
sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, LONGITUD_MSJ+1) < 0 )
return 1;
else printf("GET frame sent\n");
...
strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));
should be replaced with
snprintf(buffer, sizeof(buffer),
"GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: TEST 0.1\r\n\r\n",
google);
if (write(socket_google, buffer, strlen(buffer)+1) < 0 ) {
close(socket_google);
return 1;
} else
printf("GET frame sent\n");
...
buffer[0] = '\0';
/* Read message from socket */
bytes_recv = read(socket_google, buffer, sizeof(buffer));
if (bytes_recv < 0) {
fprintf(stderr, "socket read error: %s\n", strerror(errno));
close(socket_google);
exit(10);
}
buffer[bytes_recv] = '\0'; /* NUL character */
/* strcpy(message,buffer); */
printf("%s\n", buffer);
...
You should also close the socket before exiting the program. Enable standard C89/90 or C99 mode of your compiler (e.g. -std=c99 for gcc) and enable warnings (e.g. -Wall for gcc), and read them. And #include the necessary header files (assuming Linux in my case) for function prototypes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> /* for gethostbyname() */
There is some casting of pointers and structs in regards to the hostname / IP address resolving, which can be confusing and easy place to make a mistake, so verify that is working as you expect it is.
in_addr_t ip;
...
GetIP(google, &ip); /* I changed the parameters */
printf("IP address = %x (%s)\n",
ip,
inet_ntoa(*((struct in_addr*)&ip)));
Actually, I've been implementing a small web proxy using my library called rzsocket link to it.
One of the most difficult things I've found when implementing the web proxy, perhaps this might also be your problem, was that, in order to make the proxy work properly, I had to set keep-alive settings false. One way of doing this in FireFox, is accessing about:config address, and setting the value of network.http.proxy.keep-alive to false.

Resources