Send data to Murano Platform from Ubuntu using C


#1

Hi,
I am new to Socket programming, I have found the program on web that uses the C code to do HTTP POST and tested it with “posttestserver.com” and its working fine.

I have read the document on http://docs.exosite.com/reference/products/device-api/http/ Write section.
But unfortunately there is no response back from the server.Kindly take a look at the code i used
and do suggest changes.

We intend to port the code to an embedded device that runs linux.

//posttestserver.com

/* http_post_simple - do a POST to an HTTP URL and return the values

Copyright GPL 2003 by Mike Chirico <mchirico@users.sourceforge.net>
Updated: Sun Jun 13 13:53:14 EDT 2004

A few things to note with this example:
  .. note the \r\n .. it needs a carrage return line feed

      "POST /test.php HTTP/1.0\r\n"
      "Host: souptonuts.sourceforge.net\r\n"

  souptonuts.sourceforge.net ip address is 66.35.250.209
  but use the dns name "souptonuts.sourceforge.net"

  A note on Content-length

     "Content-length: 36\r\n\r\n"
    ->"mode=login&user=test&password=test\r\n"<-- 36 characters

  36 is the length of the string "mode=login&user=test&password=test\r\n"
  If the string is changed, then length must be adjusted.

 Reference:
  http://souptonuts.sourceforge.net/chirico/test.php
  http://souptonuts.sourceforge.net/code/test.php.html

 Download:
  http://prdownloads.sourceforge.net/cpearls/spider.tar.gz?download

*/

#include arpa/inet.h”
"#include assert.h"
"#include errno.h"
"#include netinet/in.h"
"#include signal.h"
"#include stdlib.h"
"#include stdio.h"
"#include string.h"
"#include sys/types.h"
"#include sys/socket.h"
"#include sys/wait.h"
"#include netdb.h"
"#include unistd.h"

#define SA struct sockaddr”
"#define MAXLINE 4096"
"#define MAXSUB 200"

#define LISTENQ 1024”

extern int h_errno;

ssize_t process_http(int sockfd, char *host, char *page, char poststr, char CIK)
{
char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
ssize_t n;
/
snprintf(sendline, MAXSUB,
“POST %s HTTP/1.0\r\n”
“Host: %s\r\n”
“Content-type: application/x-www-form-urlencoded\r\n”
“Content-length: %d\r\n\r\n”
"%s", page, host, strlen(poststr), poststr);
/
snprintf(sendline, MAXSUB, “POST %s HTTP/1.1\r\n”, page);
write(sockfd, sendline, strlen(sendline));
printf("%s", sendline);

snprintf(sendline, MAXSUB, "Host: %s\r\n", host);
write(sockfd, sendline, strlen(sendline));
printf("%s", sendline);

snprintf(sendline, MAXSUB, "X-Exosite-CIK: %s\r\n", CIK);
write(sockfd, sendline, strlen(sendline));
printf("%s", sendline);

snprintf(sendline, MAXSUB, "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n");
write(sockfd, sendline, strlen(sendline));
printf("%s", sendline);

snprintf(sendline, MAXSUB, "Content-Length: %d\r\n\r\n", strlen(poststr));
write(sockfd, sendline, strlen(sendline));
printf("%s", sendline);

snprintf(sendline, MAXSUB, "%s", poststr);
write(sockfd, sendline, strlen(sendline));
printf("%s", sendline);




while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
	recvline[n] = '\0';
	printf("%s", recvline);
}
return n;

}
int main(void)
{
int sockfd;
struct sockaddr_in servaddr;

char **pptr;
//********** You can change. Puy any values here *******
char *hname =  "z16ux1r0qemm80000.m2.exosite.io";
char *page  =  "/onep:v1/stack/alias";
char *CIK   =  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Actual CIK was passed here.
char *poststr = "temperature=12\r\n";
//*******************************************************

char str[50];
struct hostent *hptr;
if ((hptr = gethostbyname(hname)) == NULL) {
	fprintf(stderr, " gethostbyname error for host: %s: %s",
		hname, hstrerror(h_errno));
	exit(1);
}
printf("hostname: %s\n", hptr->h_name);
if (hptr->h_addrtype == AF_INET
    && (pptr = hptr->h_addr_list) != NULL) {
	printf("address: %s\n",
	       inet_ntop(hptr->h_addrtype, *pptr, str,
			 sizeof(str)));
} else {
	fprintf(stderr, "Error call inet_ntop \n");
}

sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(443);
inet_pton(AF_INET, str, &servaddr.sin_addr);

if(connect(sockfd, (SA *) & servaddr, sizeof(servaddr)) == -1)
{
	perror("Connect error");
	exit(2);
}

process_http(sockfd, hname, page, poststr, CIK);
close(sockfd);
exit(0);

}

PS: the include files are modified so as to look neat in the forum.(they were enlarged in preview section)

Thanks
John


#2

I also use Murano from C and have found it to be very easy to interface with using libcurl. Our solution uses SSL, which is obviously much easier to try when you have the curl library available. If that’s an option for your environment I would recommend trying it.

I think SSL is actually required when using a product domain (%s.m2.exosite.com) but don’t quote me on that. I’ve never used Murano without HTTPS so I don’t know if it’s possible.


#3

Hello Isaac,

Thanks for the reply,

I will try with libcurl as you mentioned , but the document provided by Exosite Murano clearly states it will support either the TLS or CIK ,
"A device may authenticate with either a TLS Client Certificate or by using a secret Token specified in the “X-Exosite-CIK” HTTP request header."
I was wondering why the code wont work since it works for other sites I have tested so far.

Thanks
john


#4

@john,

Thanks for posting! I think you are running into a pair of issues, and I also think we can clear things up.

Exosite wants to talk HTTPS on 443 out-of-the-box.

@iraway was right that by default Exosite’s Device API requires that a device connect to us

I think SSL is actually required when using a product domain (%s.m2.exosite.com) but don’t quote me on that. I’ve never used Murano without HTTPS so I don’t know if it’s possible.

When your Product is first setup we provide you a host that is only listening on port 443. I think it looks like you changed the port, but you didn’t use TLS to connect to our server. Because we want to impose good security practices, we expect traffic to be secured. If you can’t implement TLS due to some constraints you can connect your devices to us in developer mode.

In our thingdev-board demo we have some instructions on how to enable the unsecured development mode host for Products:

  1. Navigate to the Product SETTINGS tab.
  1. Select the checkbox to “Allow development devices to connect”.

This is necessary because the ESP8266 uses unsecured HTTP connections to communicate with Murano over a unique path. While HTTPS connections are opened with ‘PID’.m2.exosite.io, HTTP connections are opened with ‘PID’.devmode-m2.exosite.io.

Client certificates are an authentication scheme not necessarily TLS.

In Exosite Murano there are three authentication methods, client certificates, CIKs, and Tokens. While client certificates are connected to TLS, they are not required to authenticate with Exosite over TLS.

You should be able to find more information on client certs here: https://tools.ietf.org/html/rfc5246#section-7.4.4

Hopefully this helps,
-Martin


#5

Hello Martin,

Thanks for the detailed description about the issue, and clearing my doubts.

Thanks
John