C HTTP uriparser lib setup - c

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!

Related

CMake CPack NSIS How to pass install location to project?

I have a project written in C. Currently it's using UNIX makefiles to compile itself for Linux, but recently I've been looking into CMake, to be more portable.
The executable, when running, needs to access some asset files that are part of the project. When using makefiles, I would just compile the project with:
make prefix=/usr
make prefix=/usr install
So while the project is compiled, it knows that it will end up in /usr, and when running, it searching for its own project files there (in something like /usr/share/my-project/).
I created a very basic CMakeLists.txt, that compiles the .exe file, and installs it together with one other asset file in the install directory. I then run the following commands to create an NSIS installer for Windows:
cmake.exe --build --config Release .
cpack.exe
Which succesfully gives me the NSIS installer. When run, it shows the user a few steps, one of them is to decide where the project will be installed, which the user can modify.
So my question is, at that point the project has already been compiled, so how can I pass to my project its own install location, so it can access files included in the project? How do other projects do this? I couldn't find much information online about it, which makes me think I might be taking the wrong approach.
For anyone stuck in a similar problem, I found one solution.
Upon looking online, this seems to be something not recommended for Unix systems, and setting the install location during compilation is pretty standard.
For windows, however, I found the function GetModuleFileNameW (GetModuleFileNameW function (libloaderapi.h)).
It returns the path to the current executable (something like C:\Program Files\<my-app>\bin\my-app.exe). I've confirmed it returns the right path, even when I install the project on different directories. It returns the result using wchar_t, so unicode directories are also supported.
Here is a small example of how it can be used:
// to keep the example simple, this is assuming maximum 1000 characters in the path
wchar_t dynamicProjectLocationW[1000];
GetModuleFileNameW(NULL, dynamicProjectLocationW, 999);
dynamicProjectLocationW[999] = L'\0';
// given a path like "C:\X\Y\bin\myapp.exe" find the second to last slash
// so we can get the path "C:\X\Y\"
wchar_t *pointer = dynamicProjectLocationW;
wchar_t *secondToLastSlash = 0;
wchar_t *lastSlash = 0;
while (pointer[0] != L'\0') {
if (pointer[0] == L'\\') {
secondToLastSlash = lastSlash;
lastSlash = pointer;
}
pointer++;
}
// cut the path short, so we can use the project path to find other files
if (secondToLastSlash) {
secondToLastSlash++;
secondToLastSlash[0] = L'\0';
}
This is solving my problem for now, so I'll be using this until a better solution is found.

Kotlin/Native Windows cinterop using built library dll

I am using Windows to follow the Kotlin-Native libcurl example here https://kotlinlang.org/docs/tutorials/native/curl.html
Unfortunately, this has been a bigger challenge then I could have imagined. I have been learning how to compile C binaries on windows from source using tools such as CMake and have followed this tutorial to build libcurl on Windows: https://jonnyzzz.com/blog/2018/10/29/kn-libcurl-windows/
After quite a few days of trial and error with the .def file for cinterop on Windows, and using compilerOpts to point to my header file for curl in my built library, I have hit a brick wall.
I can't seem to get Gradle to recognize the dll file. Task ':linkDebugExecutableMingw' keeps failing. I have no idea where I am supposed to put the dll file. I have tried putting it in to the build output folder next to the exe, but it still fails to compile, with this error:
C:\Users\yous\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1\bin\ld: C:\Users\yous\AppData\Local\Temp\konan_temp6326583690522756621\result.o:out:(.rdata$.refptr.knifunptr_sample35_curl_easy_strerror[.refptr.knifunptr_sample35_curl_easy_strerror]+0x0): undefined reference to `knifunptr_sample35_curl_easy_strerror'
And a similar list of header file errors, then the final message is:
e: C:\Users\yabde\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1/bin/clang++ invocation reported errors
This is after I succesfully located the header files. I believe this is an issue with the dll file not being included.
Here is my relevant Gradle build script:
mingwX64("mingw") {
compilations.main {
cinterops {
libcurl {
// Def-file describing the native API.
// The default path is src/nativeInterop/cinterop/<interop-name>.def
defFile project.file("src/nativeInterop/cinterop/libcurl.def")
// Package to place the Kotlin API generated.
packageName 'libcurl'
// Options to be passed to compiler by cinterop tool.
compilerOpts '-Isrc\\nativeInterop\\cinterop\\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\\include -o libcurl'
//linkerOpts '-Isrc\\nativeInterop\\cinterop\\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\\bin'
// Directories for header search (an analogue of the -I<path> compiler option).
//includeDirs.allHeaders("path1", "path2")
// Additional directories to search headers listed in the 'headerFilter' def-file option.
// -headerFilterAdditionalSearchPrefix command line option analogue.
includeDirs.headerFilterOnly("src/nativeInterop/cinterop/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/include")
// A shortcut for includeDirs.allHeaders.
//includeDirs("include/directory", "another/directory")
}
}
}
binaries {
executable {
// Change to specify fully qualified name of your application's entry point:
entryPoint = 'sample.main'
// Specify command-line arguments, if necessary:
//runTask?.args('-Lsrc/nativeInterop/cinterop/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/bin')
runTask?.args('')
}
}
}
I believe this issue may be with linker options to locate the dll, but uncommenting the linkerOpts line does not help.
I think I have given up on Kotlin/Native and will be sticking to C for data-oriented native programming...
EDIT:
Also, note that any text commented out is things that I have attempted
Ok so, this is my def file:
headers = curl/curl.h
headerFilter = curl/*
compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu
linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl
linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl
linkerOpts.mingw = -Llibcurl-vc-x86-release-dll-ipv6-sspi-winssl/lib
Ok so, this is my project structure:
I followed the same steps (jonyzzz blog). I created a Libcurl static example for Kotlin-Native. Support for gzip and SSL. Compile to standalone exe, no need for dll
https://github.com/carlosrafp/Libcurl-Kotlin-Native-standalone
I built the static libraries supplied on the repository with mingw64 (gzip and libcurl) and msys2/mingw (openssl)
I went through this question several times when looking for a solution for statically linking libcurl with my binary.
In the end, I ended up using WinInet for the HTTP communication on Windows. Linux and macOS binary still rely on ktor clients with libcurl.
See my example of how to use WinInet API with Kotlin MPP: https://github.com/localazy/kotlin-mpp-wininet
For a simple HTTP communication, WinInet API is good enough and the resulting binary is much smaller and in my case, it has no additional dependencies.

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.

Compiling with OpenSSL ssl_conn errors

I am trying to compile a small .c file which uses OpenSSL includes, at first I had problems compiling but I solved it installing libssl-dev and that solved the include errors.
But now when I try to compile I get:
‘ssl_conn’ has no member named ‘encrypted’
‘ssl_conn’ has no member named ‘write_seq’
‘ssl_conn’ has no member named ‘read_seq’
The code for the lines of the error is:
ssl_conn* sslCon;
sslCon->encrypted = 0;
sslCon->write_seq = 0;
sslCon->read_seq = 0;
A friend told me it could be because the .c file was coded for an old version of OpenSSL, but I am not sure. Does someone knows what could be causing this and how to solve it?
ssl_conn is not part of the OpenSSL API and never was. I only found reference to it in some sample code exploiting OpenSSL, and it was defining it itself. Assuming you aren't trying to use that exploit code, my guess is there's an example floating around online from which you got the code you are trying to compile. So check your definition of ssl_conn and ensure it has the fields that are missing.

How to use a C library from D?

Today I heard about the D programming and that it is compatible to C code. Nevertheless I haven't found any information on whether it is possible to use C libraries like GTK or PortAudio from D?
If it is possible, could you explain how to do this?
It is possible to call C libraries from D. What you need to do is to convert the C header files to D. For the most part this is pretty straightforward, and there is a hard-to-use command-line tool to help automate the process. It's never really worked for me on anything but toy examples, but it could be a good start to see the kind of transformations that need to be done. Just put a snippet you're having trouble translating into a header by itself and see what htod does with it.
The biggest problem you'll usually encounter is creative use of the C preprocessor. Some things can be turned into version() statements in D, but not all.
As for actually compiling and linking with the code, on unix-like platforms I think you can compile and link in the C code using GCC. On Windows you either have to compile the C files using DMC and link with DMD. Or you can compile the C code into a DLL using any compiler capable of that, and then to link with DMD you need to make a DMD-compatible import lib out of the DLL. This can be done using the implib tool found in the free Basic Utilities Package available from DigitalMars.
There are also a lot of these header translations have already been done. It's useful to browse the Bindings project of Dsource first, or ask on the digitalmars D newsgroups first before embarking on something big like translating GTK headers. A lot of popular libraries like GTK have already been wrapped (e.g. here: GTKD)
D code can be linked with C object files, and can interact with C dlls, but you'll need to generate a D module from the C header file you want to use. The official D website has a guide for doing that very thing.
Popular alternative is to load the library during the run-time. Here is an example how to load libpng and call a libpng function:
module libpngtest;
import std.stdio;
import core.sys.posix.dlfcn;
alias uint function() png_access_version_number_t;
int main() {
auto lib = dlopen("libpng.so".ptr, RTLD_LAZY | RTLD_LOCAL);
if (lib is null) {
writeln("EEEK!");
writeln(to!string(dlerror()));
return -1;
} else {
writeln("WOOT!");
auto png_access_version_number = cast(png_access_version_number_t)dlsym(lib, "png_access_version_number");
writeln(png_access_version_number());
}
if (dlclose(lib) == 0) {
return 0;
} else {
return -1;
}
} // main() function
// compile: dmd libpngtest.d -L-ldl
// run: ./libpngtest
Use the DPaste to test it: http://www.dpaste.dzfl.pl/917bc3fb
You need to write C bindings.
This answer explain how.
Take a look at http://dsource.org
There are many projects that might help you to get start with

Resources