Getting IP of post client - c

Well I know that I should have tried a lot before asking here, but my problem is. It's hard to get structured reference of fcgi documentation. So i hope you won't downvote me that much, even in aspect of little lack of self study.
I'm trying to find a way to archive the IP of the requesting client.
As I guess (if I understood right) I could request the HTTP header of the connection by the FCGX_stream handle. But I would prefer a easier way if there is one.
My first try was checking it about the getenv as provided in the first fcgi tutorial, but as I tryed it as described here:
https://stackoverflow.com/a/4107212/2003898
It compiled fine, but on first request my fcgi app just crashed. (but it wouldn't solve my problem anyway as I figured out the get env is just requesting MY, so the host ones, env's)
I were also trying arround with the
*FCGX_GetParam(const char *name, FCGX_ParamArray envp);
function. But either I'm to stupid to use or it is also just providing my local evniroment and not the POST side's one.
So if anyone could tell me how to acces those data (prefered without extracting from HTTP header) or how to use FCGX_GetParam to acces it,
I would be thankfull.
EDIT:
#include "fcgi_stdio.h"
#include <stdlib.h>
int main()
{
int count = 0;
while(FCGI_Accept() >= 0)
{
for (count = 0; environ[count] != NULL; count++)
{
printf("%s\n", environ[i]);
}
}
return 0;
}

Use getenv("REMOTE_ADDR")
The remote IP address isn't included in the HTTP headers anyway

Related

Compiling the Paho MQTT C Client Library

I want to integrate the [Paho MQTT C Client Library][1] to one of my C programs. Since I am from EE, I find it difficult achieve this task. However my efforts are described below along with my problem.
The purpose is to simply use username, password and subscribe to perticular MQTT topic using a C program. If this is done, I can proceed to do the rest of things such as saving the data to a .txt file and etc which I am completely familiar with in C.
Since I am from an electronics background, my familiarity with compiling complex projects like these and making them work is not really at best but I really want to get there.
I do know how to compile small projects using "make all" and use the binary executable produced to use such software. I simply do, make clean and make all.
However, the idea of compiling a library doesn't make sense to me. Why do I need to compile any library in the first place? Usually, when I write C program, I integrate someone else's library by uisng #include "library2.h". From this method, I am able to call functions in that library and get things done. Why cant we use Paho the same way? I do not understand why Paho MQTT C library requires compiling. I would like to know the technical reason for this.
Secondly, and most importantly, I would really appreciate if you can provide me step by step guidance to write a simple C program that can subscribe to my MQTT server to printout the messages published in that topic. I use Ubuntu 14.10 LTS.
I understand that this question may be a very basic question. I have asked answers to this question from other people in the lab and also tried fiddling with the example available on [1]
When I do so, I am bombarded with many error messages and I just cant seem to get this to work. May be one of you can shred some light with proper guiding steps for me to get my client to work.
I would really appreciate your efforts on this. It would help me a lot.
update:
As per request of Gaurav Pathak I post my erros below.
Step 1: I downloaded the coursecode of Paho MQTT libray from
github dot com/eclipse/paho.mqtt.c
Step 2: I went into the /home/user/paho.mqtt.c/ and ran Make Clean and Make All
Step 3: Then, I made a copy of the following example code provided on http://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/subasync.html in side /home/user/paho.mqtt.c/src . This example code is given below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ExampleClientSub"
#define TOPIC "MQTT Examples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
volatile MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
int i;
char* payloadptr;
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: ");
payloadptr = message->payload;
for(i=0; i<message->payloadlen; i++)
{
putchar(*payloadptr++);
}
putchar('\n');
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
Step 3: Then I ran GCC client.c -o client
user#userpc:~/paho.mqtt.c/src$ gcc client.c -o client
/tmp/ccEkSjap.o: In function `msgarrvd':
client.c:(.text+0xc5): undefined reference to `MQTTClient_freeMessage'
client.c:(.text+0xd1): undefined reference to `MQTTClient_free'
/tmp/ccEkSjap.o: In function `main':
client.c:(.text+0x1eb): undefined reference to `MQTTClient_create'
client.c:(.text+0x21d): undefined reference to `MQTTClient_setCallbacks'
client.c:(.text+0x233): undefined reference to `MQTTClient_connect'
client.c:(.text+0x29a): undefined reference to `MQTTClient_subscribe'
client.c:(.text+0x2cb): undefined reference to `MQTTClient_disconnect'
client.c:(.text+0x2da): undefined reference to `MQTTClient_destroy'
collect2: error: ld returned 1 exit status
[1]: eclipse dot org/paho/files/mqttdoc/MQTTClient/html/index.html
However, the idea of compiling a library doesn't make sense to me.
Compiling the library from source is the first thing that you need to do. Even if you don't want to compile the library to create an archive .a file you need to include the source code (*.c and *h files) of the same library in your project.
Why do I need to compile any library in the first place?
Very Good question! The answer is because it's not easy to find a pre-compiled library for specific processor architecture. You may get a pre-compiled library for x86 or x64 but it is difficult to find a pre-compiled library for other architectures for e.g. Power PC, ARM, etc. So, the best way is to download the source code and either make a library out of it to statically link with your project or just directly include the source code in your existing project and compile it with your project.
Usually, when I write C program, I integrate someone else's library by
uisng #include "library2.h".
Don't you need to link the source of the library with your project? Just including the headers won't link the library. I guess you need to first understand what are the steps of the compilation process, and especially what is the significance of linker and linking process.
Please read this post for getting an understanding of how the program is compiled and linked.
Also, please read this post to understand the difference between library and header file.
When I do so, I am bombarded with many error messages and I just cant
seem to get this to work.
If you provide your code and tell us your specific error then may be we can help.

C HTTP uriparser lib setup

I am currently working on a simple HTTP proxy as an educational personal project. I am fairly new to socket programming, C, and the need for and use of specific libraries.
After reading up on different ways to parse HTTP request URLs in C, I found that using parsing libraries, like uriparser, seemed to be the most popular and the safest choice.
Unfortunately, I have really been struggling to get this library working properly.
After downloading the library from here, I unpacked the "tarball" and ran the following:
./configure
make
sudo make install
The output for 'sudo make install' claimed that that the libraries were installed in '/usr/local/lib', which they have been. However, when I try to use a UriUriA obj as shown in Uriparser's documentation here, the object is clearly not recognized.
Is this library installed in the right place?
Am I missing something obvious like not including a header file for this library? I could't find one in the linked documentation.
RELEVANT CODE:
(functionality is pretty bare right now, mainly pointing at UriUri instantiation which still produces unknown type compile error. I still have yet to be able to use the lib)
int parse_req(char * buffer, char * url){
UriUriA uri;
char *reqs[] = {"GET ", "CONNECT "};
int i = 0;
//Determine Request Types
while(reqs[i] != NULL){
int check = strncmp(reqs[i],buffer,strlen(reqs[i]));
if (check == 0){
break;
}
i++;
}
return -1;
}
If anyone has any experience with this library, any help is appreciated! Thanks!

Mac sandbox: running a binary tool that needs /tmp

I have a sandboxed Cocoa app that, during an export process, needs to run a third party command-line tool. This tool appears to be hardcoded to use /tmp for its temporary files; sandboxing doesn't permit access to this folder, so the export fails.
How can I get this tool to run? I don't have access to its source code, so I can't modify it to use NSTemporaryDirectory(), and it doesn't appear to respect the TMP or TEMPDIR environment variables. For reasons I don't understand, giving myself a com.apple.security.temporary-exception.files.absolute-path.read-write entitlement doesn't seem to work, either.
Is there some way to re-map folders within my sandbox? Is there some obscure trick I can use? Should I try to patch the tool's binary somehow? I'm at my wit's end here.
I was able to get user3159253's DYLD_INSERT_LIBRARIES approach to work. I'm hoping they will write an answer describing how that works, so I'll leave the details of that out and explain the parts that ended up being specific to this case.
Thanks to LLDB, elbow grease, and not a little help from Hopper, I was able to determine that the third-party tool used mkstemp() to generate its temporary file names, and some calls (not all) used a fixed template starting with /tmp. I then wrote a libtmphack.dylib that intercepted calls to mkstemp() and modified the parameters before calling the standard library version.
Since mkstemp() takes a pointer to a preallocated buffer, I didn't feel like I could rewrite a path starting with a short string like "/tmp" to the very long string needed to get to the Caches folder inside the sandbox. Instead, I opted to create a symlink to it called "$tmp" in the current working directory. This could break if the tool chdir()'d at an inopportune time, but fortunately it doesn't seem to do that.
Here's my code:
//
// libtmphack.c
// Typesetter
//
// Created by Brent Royal-Gordon on 8/27/14.
// Copyright (c) 2014 Groundbreaking Software. This file is MIT licensed.
//
#include "libtmphack.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>
//#include <errno.h>
#include <string.h>
static int gbs_has_prefix(char * needle, char * haystack) {
return strncmp(needle, haystack, strlen(needle)) == 0;
}
int mkstemp(char *template) {
static int (*original_mkstemp)(char * template) = NULL;
if(!original_mkstemp) {
original_mkstemp = dlsym(RTLD_NEXT, "mkstemp");
}
if(gbs_has_prefix("/tmp", template)) {
printf("libtmphack: rewrote mkstemp(\"%s\") ", template);
template[0] = '$';
printf("to mkstemp(\"%s\")\n", template);
// If this isn't successful, we'll presume it's because it's already been made
symlink(getenv("TEMP"), "$tmp");
int ret = original_mkstemp(template);
// Can't do this, the caller needs to be able to open the file
// int retErrno = errno;
// unlink("$tmp");
// errno = retErrno;
return ret;
}
else {
printf("libtmphack: OK with mkstemp(\"%s\")\n", template);
return original_mkstemp(template);
}
}
Very quick and dirty, but it works like a charm.
Since #BrentRoyal-Gordon has already published a working solution I'm simply duplicating my comment which inspired him to produce the solution:
In order to fix a program behavior, I would intercept and override some system calls with the help of DYLD_INSERT_LIBRARIES and a custom shared library with a custom implementation of the given system calls.
The exact list of the syscalls which need to be overridden depends on nature of the application and can be studied with a number of tools built upon MacOS DTrace kernel facility. E.g. dtruss or Hopper. #BrentRoyal-Gordon has investigated that the app can be fixed solely with an /appropriate/ implementation of mkstemp.
That's it. I'm still not sure that I've deserved the bounty :)
Another solution would be to use chroot within the child process (or posix_spawn options) to change its root directory to a directory that is within your sandbox. Its “/tmp” will then be a “tmp” directory within that directory.

c, opencv - accessing camera JPG image over ip

I have read many, many threads about streaming images over IP in OpenCV 2.3.1, but I still cannot get my program to work.
I downloaded IP Webcam for Android from https://market.android.com/details?id=com.pas.webcam&hl=en, and recently learned OpenCV to retrieve images from my Android phone camera.
Its built-in manual said that the image from the phone camera can be located at http://the.phone.ip.address:8080/shot.jpg. I have opened it from browser several times and it always looks fine. I also built OpenCV manually, with FFmpeg support.
So far I've tried
CvCapture* webcam = cvCaptureFromFile("http://192.168.1.220:8080/shot.jpg");
but it returns NULL and outputs
[image2 # 0xd701e0]Could not find codec parameters (Video: mjpeg, yuv420p)
I also tried replacing http with rtsp, but it still doesn't work. I also tried to replace the url with some other image url (one direct link to random image from Google Images, and one from localhost) and it always kills with a segfault.
Here's my full source
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
int main(int argc, char* argv[])
{
CvCapture* webcam = cvCaptureFromFile("http://192.168.1.220:8080/shot.jpg");
if(!webcam)
{
fprintf(stderr, "cannot open webcam\n");
return 1;
}
IplImage* img = cvQueryFrame(webcam);
if(!img)
{
fprintf(stderr, "cannot get image\n");
return 1;
}
cvNamedWindow("test", CV_WINDOW_AUTOSIZE);
cvShowImage("test", img);
cvWaitKey(0);
cvReleaseImage(&img);
/**/ cvReleaseCapture(&webcam); /**/
cvDestroyWindow("test");
return 0;
}
Can OpenCV really read images over IP, or am I missing something?
I'm not specifically familiar with openCV, but having spent a minute looking at the docs, two things jump out at me:-
First off, your're not dealing with a true video stream here: your android app just makes the current JPEG capture available and you have to continually re-sample it. Because it's an Image, not a Video, you should use cvLoadImage() instead.
Second, you're passing a URL, not a filename. You'll need a way to use HTTP to fetch the image to a local file before you try opening it with openCV.
I'd suggest you save a snapshot of the JPEG file locally from your browser, and then try getting your code working with that. Once you have it working from a local file, try adding the HTTP fetching stuff.
While it would be /awesome/ if that was supported, it doesn't appear to be. Note that OSes handle opening files differently from URLs (obviously) so it's not something that would be supported by default - you can't fopen() a URL. If OpenCV specifically did support it, it would be possible, but I have some evidence that they do not:
Read image from URL into OpenCV states it is not possible, and solves the problem by using an HTTP stream
This forum post from 2010 also suggests that it is not supported
This email from 2005 has a response that says the same thing.
Here's what you can do:
Download the image some other way - perhaps by using a system() call to wget, perhaps by using a library to download the file into memory
At least one source says you may use Processing's loadImage() to load from a URL.
Further searching on Roddy answer makes that I've made things work for me.
Unfortunatelly it's not nice and windows only solution. But only way to get jpg from this application is to fetch http in some way. There are many libs which can help for example libcurl, boost::asio.
I've used urlmon.lib to make things work for me:
#inlcude <opencv2\opencv.hpp>
#include <UrlMon.h>
#include <tchar.h>
#pragma comment(lib,"urlmon.lib")
int main()
{
for(;;)
{
HRESULT hr = URLDownloadToFile(NULL,_T("http://192.168.1.104:8080/shot.jpg"),
_T("D:/test.jpg"),0,NULL);
IplImage *test = cvLoadImage("D:/test.jpg");
cvShowImage("test",test);
cvWaitKey(30);
}
}
This application can also stream mjpg as I've suggested in comments. OpenCV VideoStream seems to have option to read from it as suggested Stream live video in openCv from localHost port (http://192.168.1.1:8080) and OpenCV with Network Cameras .
I've tried also this solution but get mp3 header missing. I hope that someone provide some answer with using videofeed from this application.

getlogin() c function returns NULL and error "No such file or directory"

I have a question regarding the getlogin() function (). I tried to get the login name of my account from the c program using this function. But the function returns a NULL. Using perror shows that the error is "No such file or directory".
I don't get what is the problem. Is there a way to get user login name in a program.
Here is a sample code:
#include <stdio.h>
#include <unistd.h>
int main()
{
char *name;
name = getlogin();
perror("getlogin() error");
//printf("This is the login info: %s\n", name);
return 0;
}
And this is the output: getlogin() error: No such file or directory
Please let me know how to get this right.
Thanks.
getlogin is an unsafe and deprecated way of determining the logged-in user. It's probably trying to open a record of logged-in users, perhaps utmp or something. The correct way to determine the user you're running as (which might not be the same as the logged-in user, but is almost always better to use anyway) is getpwuid(getuid()).
Here is a good link I found explaining that it may not work: getlogin
Here is a quote from it:
Unfortunately, it is often rather easy to fool getlogin(). Sometimes it does not work at all, because some program messed up the utmp file
It works fine for me if I comment perror call.
From man:
getlogin() returns a pointer to a string containing the name of the user logged in on the controlling terminal of the process, or a null pointer if this information cannot be determined.'
So you should do:
#include <stdio.h>
#include <unistd.h>
int main()
{
char *name;
name = getlogin();
if (!name)
perror("getlogin() error");
else
printf("This is the login info: %s\n", name);
return 0;
}
According to the man page the error (ENOENT) means:
There was no corresponding entry in the utmp-file.
I typically use getpwent() along with a call to geteuid() and getegid(). This gives me all of the information that I might possibly need to know (at least as far as /etc/passwd has to offer) and tells me if I'm running as setuid / setgid, which is helpful when programming defensively.
I have written several programs for my company that outright refuse to work if someone tries to setuid them and change ownership to root, or refuse to run as root if being called by a system user (www-data, nobody, etc).
As others have said, reading from utmp is a very bad idea for this purpose.

Resources