adding new functions...

master
Steffen Pohle 3 weeks ago
parent 5f35e868d5
commit 7da4ffd4cb

@ -8,7 +8,7 @@ DEFAULT_TCPPORT=6131
DEFAULT_UDPPORT=6131
DEFAULT_SERVER=localhost
OBJLIB=network.o udp.o tcp.o unix.o ssl.o
OBJLIB=network.o udp.o tcp.o unix.o ssl.o webserver.o json.o
INCLIB=UDPTCPNetwork.h
DISTNAME=libUDPTCPNetwork-$(VERSION)
@ -17,7 +17,7 @@ noconfig: help
endif
all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl
all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl test-json
help:
echo "set up configuration"
@ -43,6 +43,9 @@ test-ssl: $(TARGET) test-ssl.o
test-udp: $(TARGET) test-udp.o
$(CXX) test-udp.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-json: $(TARGET) test-json.o
$(CXX) test-json.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
keygen:
# openssl req -nodes -new -newkey rsa:2048 -sha256 -out csr.pem -keyout privkey.pem
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privkey.pem -out cert.pem

@ -0,0 +1,18 @@
# libUDPTCPNetwork
library collection of usefull network function prepared for windows and linux.
## support
the following connection types are supported
- TCP
- UDP
- SSL
- Unix-Sockets (only on linux)
## additional stuff
- JSON
- WebServer (work in progress)
## Sample Code
for better understanding see the test-* sample code.

@ -0,0 +1,77 @@
#ifndef _JSON_H_
#define _JSON_H_
#include <list>
#include <string>
#include <string.h>
enum {
JSON_T_NONE,
JSON_T_STRING,
JSON_T_NUMBER,
JSON_T_OBJECT,
JSON_T_ARRAY
};
class JSONElement {
public:
int type;
std::string name;
std::string value;
JSONElement() { Clear(); };
~JSONElement() {};
void Clear() { type = JSON_T_NONE; name = ""; value = ""; };
void Set (std::string n, double v);
void Set (std::string n, int v);
void Set (std::string n, int64_t v);
void Set (std::string n, std::string v);
void SetArray (std::string n, std::list<JSONElement> *l);
void SetAddArray (std::string n, std::string jpstring);
void SetObject (std::string n, std::string s);
static std::string StringAddEscape(std::string *s);
static std::string StringRemoveEscape(std::string *s);
std::string GetString();
};
class JSONParse {
private:
std::string jsondata;
std::list<JSONElement> names;
public:
JSONParse() { Set("{}"); };
JSONParse(std::string json) { Set(json); };
~JSONParse() {};
void Clear();
int Set(std::string json);
int GetValue(std::string varname, std::string *dest);
int GetValueInt(std::string varname, int *dest);
int GetValueInt64(std::string varname, int64_t *dest);
int GetValueString(std::string varname, std::string *dest);
int GetObject(std::string varname, JSONParse *dest);
int GetIdx(std::string src, int idx, std::string *dest);
int GetValueIdx(std::string varname, int idx, std::string *dest);
int GetObjectIdx(std::string varname, int idx, JSONParse *dest);
std::list<JSONElement> GetElements();
void AddObject (JSONElement element);
void AddObject (std::string name, int val);
void AddObject (std::string name, int64_t val);
void AddObject (std::string name, std::string val);
void AddObject (std::string name, double val);
void AddObject (std::string name, JSONParse jp);
int LoadFromFile (std::string filename);
int SaveToFile (std::string filename);
std::string ToString();
};
#endif // _JSON_H_

@ -40,6 +40,7 @@
#endif
#include "UDPTCPNetwork-json.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
@ -69,6 +70,8 @@ char *itoa(char* buffer, int number, int size);
void UDPTCPNetwork_Startup();
#define UDPTCPNetwork() if(UDPTCPNetwork_init == 0) UDPTCPNetwork_Startup()
std::string string_to_lower(std::string s);
std::string string_to_upper(std::string s);
int file_is_readable (const char *fname);
/************************************************************************
@ -184,7 +187,8 @@ public:
int Close(); // returns socket
};
std::string getsha256sum(std::string *in);
std::string getrandomtext(int numbytes);
/************************************************************************
* unix socket related functions

@ -0,0 +1,605 @@
#include <list>
#include <string>
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "UDPTCPNetwork-json.h"
/***********************************************************************
***********************************************************************
*
* JSONParse
*
***********************************************************************
***********************************************************************
*/
// FIXME: need to test embedded arrays
enum {
STEP_NONE = 0,
STEP_STARTNAME,
STEP_NAME,
STEP_STARTVALUE,
STEP_VALUE,
STEP_END
};
/////////////////////////////////////////////////////////
//
// clear out all data
//
void JSONParse::Clear() {
jsondata = "";
names.clear();
}
/////////////////////////////////////////////////////////
//
// read every element and keep only this in memory.
//
int JSONParse::Set(std::string json) {
int i;
int step;
int level;
bool ignorenext;
JSONElement jelement;
Clear();
// find start and read until end
for (step = STEP_NONE, i = 0, ignorenext = false; i < (int) json.length(); i++) {
// need to copy next character
// debug (0, "JSONParse: step:%d i:%d name:'%s' value:'%s'", step, i, jelement.name.c_str(), jelement.value.c_str());
if (ignorenext) {
ignorenext = false;
if (step == STEP_NAME) jelement.name += json[i];
if (step == STEP_VALUE) jelement.value += json[i];
}
// searching for startname
else if (step == STEP_NONE) {
if (json[i] == '{') {
step = STEP_STARTNAME;
continue;
}
}
// searching for startname
else if (step == STEP_STARTNAME) {
if (json[i] == '"') {
step = STEP_NAME;
continue;
}
}
// copy name
else if (step == STEP_NAME) {
if (json[i] == '"') {
step = STEP_STARTVALUE;
continue;
}
else {
jelement.name += json[i];
continue;
}
}
// searching for startvalue
else if (step == STEP_STARTVALUE) {
if (json[i] == '"') {
step = STEP_VALUE;
jelement.type = JSON_T_STRING;
continue;
}
if (json[i] == '{') {
step = STEP_VALUE;
level = 0;
jelement.type = JSON_T_OBJECT;
jelement.value = "{";
continue;
}
if (json[i] == '[') {
step = STEP_VALUE;
level = 0;
jelement.type = JSON_T_ARRAY;
jelement.value = "[";
continue;
}
if ((json[i] >= '0' && json[i] <= '9') ||
(json[i] == '+' || json[i] == '-')) {
step = STEP_VALUE;
level = 0;
jelement.type = JSON_T_NUMBER;
jelement.value = json[i];
continue;
}
}
// copy value
else if (step == STEP_VALUE) {
if (jelement.type == JSON_T_STRING) {
if (json[i] == '"') step = STEP_END;
else jelement.value += json[i];
continue;
}
else if (jelement.type == JSON_T_OBJECT) {
if (json[i] == '}' && level == 0) {
jelement.value += json[i];
step = STEP_END;
}
else {
if (json[i] == '{') level++; // increase level
if (json[i] == '}') level--; // decrease level
jelement.value += json[i];
}
continue;
}
else if (jelement.type == JSON_T_ARRAY) {
if (json[i] == ']' && level == 0) {
jelement.value += json[i];
step = STEP_END;
}
else {
if (json[i] == '[') level++; // increase level
if (json[i] == ']') level--; // decrease level
jelement.value += json[i];
}
continue;
}
else if (jelement.type == JSON_T_NUMBER) {
if ((json[i] < '0' || json[i] > '9') && json[i] != '.' &&
json[i] != '+' && json[i] != 'e' && json[i] != 'E') step = STEP_END;
else {
jelement.value += json[i];
continue;
}
}
}
// another element?
if (step == STEP_END) {
if (json[i] == ',') {
// debug (0, "* JSON.Set Add name:%s", jelement.name.c_str());
if (jelement.type != JSON_T_NONE) {
// debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type);
names.push_back (jelement);
}
jelement.Clear();
step = STEP_STARTNAME;
}
continue;
}
}
// debug (0, "* JSON.Set Add name:%s", jelement.name.c_str());
if (jelement.type != JSON_T_NONE) {
// debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type);
names.push_back (jelement);
}
return 0;
};
int JSONParse::GetValue(std::string varname, std::string *dest) {
std::list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
*dest = "";
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
*dest = iter->value;
return 1;
}
}
return 0;
};
int JSONParse::GetValueInt(std::string varname, int *dest) {
std::string s;
int res = GetValue(varname, &s);
if (res) {
*dest = atoi (s.c_str());
return 1;
}
return 0;
};
int JSONParse::GetValueInt64(std::string varname, int64_t *dest) {
std::string s;
int res = GetValue(varname, &s);
if (res) {
*dest = atol (s.c_str());
return 1;
}
return 0;
};
int JSONParse::GetValueString(std::string varname, std::string *dest) {
std::string s;
int res = GetValue(varname, &s);
if (res) {
*dest = JSONElement::StringRemoveEscape(&s);
return 1;
}
return 0;
};
int JSONParse::GetObject(std::string varname, JSONParse *dest) {
std::list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
dest->Set(iter->value);
return 1;
}
}
return 0;
};
#define MAXRECURSIVE 255
/// @brief Reads the source and returns the string of element requested.
/// @param src source json array
/// @param idx index to read
/// @param dest destiantion of the string
/// @return 0 not found else 1
int JSONParse::GetIdx(std::string src, int idx, std::string *dest) {
char recursive[MAXRECURSIVE];
int i = 0, rcnt = 0, cnt = 0;
// debug ("src:%s\n\n", src.c_str());
(*dest) = "";
for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0;
for (i = 0; i < (int) src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
/* if (src[i] == '[' || src[i] == ']' || src[i] == '"' || src[i] == ',' || src[i] == '}' || src[i] == '{') {
int _i;
debug ("src[i]:%c i:%d rcnt:%d cnt:%d idx:%d recursive:", src[i], i, rcnt, cnt, idx);
for (int _i = 0; _i < rcnt; _i++) printf ("%c", recursive[_i]);
printf ("\n");
}
*/
if (src[i] == '[') {
recursive[rcnt++] = src[i];
continue;
}
else if (src[i] == '{' ) recursive[rcnt++] = src[i];
else if (src[i] == '}' && recursive[rcnt-1] == '{') rcnt--;
else if (src[i] == '"' && recursive[rcnt-1] == '"') rcnt--;
else if (src[i] == '"') recursive[rcnt++] = src[i];
else if (src[i] == ',' && rcnt == 1) {
cnt++;
continue;
}
else if (src[i] == ']' && rcnt > 0) {
continue;
}
if (rcnt > 0 && cnt == idx) {
(*dest) += src[i];
if (src[i] == '\\') (*dest) += src[i];
}
else {
if (src[i] == '\\')i++;
}
}
//
// final checks
if (cnt == 0 && idx == 0 && // empty source/array?
dest->size() == 0) return 0; //
if (cnt >= idx) return 1; // found the right element
return 0; // element not found
}
#undef MAXRECURSIVE
int JSONParse::GetValueIdx(std::string varname, int idx, std::string *dest) {
std::list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
return GetIdx(iter->value, idx, dest);
}
}
return 0;
};
int JSONParse::GetObjectIdx(std::string varname, int idx, JSONParse *dest) {
std::list<JSONElement>::iterator iter;
std::string deststr;
int ret = 0;
if (dest == NULL) return 0;
for (iter = names.begin(); iter != names.end(); iter++) {
// debug ("name:%s value:%s\n", iter->name.c_str(), iter->value.c_str());
if (varname.compare(iter->name) == 0) {
ret = GetIdx(iter->value, idx, &deststr);
if (ret == 1) dest->Set(deststr);
// debug ("Return: %s\n", deststr.c_str());
return ret;
}
}
return 0;
};
std::list<JSONElement> JSONParse::GetElements() {
std::list<JSONElement> l;
std::list<JSONElement>::iterator iter;
l.clear();
for (iter = names.begin(); iter != names.end(); iter++) {
l.push_back(*iter);
}
return l;
};
void JSONParse::AddObject (JSONElement element) {
names.push_back (element);
};
void JSONParse::AddObject (std::string name, JSONParse jp) {
JSONElement je;
je.SetObject(name, jp.ToString());
names.push_back(je);
};
void JSONParse::AddObject (std::string name, int val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
void JSONParse::AddObject (std::string name, int64_t val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
void JSONParse::AddObject (std::string name, std::string val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
void JSONParse::AddObject (std::string name, double val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
std::string JSONParse::ToString() {
std::list<JSONElement>::iterator iter;
std::string output;
int level, i;
output = "{";
for (level = 1, iter = names.begin(); iter != names.end(); iter++) {
if (iter != names.begin()) output += ",";
output += "\n";
for (i = 0; i < 4*level; i++) output += " ";
output += iter->GetString();
}
output += "\n}\n";
return output;
};
int JSONParse::LoadFromFile(std::string filename) {
int fd;
struct stat fs;
char *buffer;
if (stat(filename.c_str(), &fs) != 0) return -1;
buffer = (char *) malloc (fs.st_size+1);
memset (buffer, 0x0, fs.st_size+1);
fd = open(filename.c_str(), O_RDONLY);
if (fd < 0) return -1;
read (fd, buffer, fs.st_size);
close (fd);
Set(buffer);
free (buffer);
return 0;
};
int JSONParse::SaveToFile(std::string filename) {
std::ofstream out(filename);
if (!out) return -1;
out << ToString();
out.close();
return 0;
};
/***********************************************************************
***********************************************************************
*
* JSONElement
*
***********************************************************************
***********************************************************************
*/
std::string JSONElement::StringAddEscape (std::string *s) {
std::string res = "";
if (s == NULL) return res;
for (int i = 0; i < s->length(); i++) {
if ((*s)[i] == '\"') {
res += "\\\"";
continue;
}
res += (*s)[i];
}
return res;
}
std::string JSONElement::StringRemoveEscape (std::string *s) {
std::string res = "";
if (s == NULL) return res;
for (int i = 0; i < s->length(); i++) {
if ((*s)[i] == '\\') {
continue;
}
res += (*s)[i];
}
return res;
}
void JSONElement::Set (std::string n, double v) {
name = n;
value = std::to_string(v);
type = JSON_T_NUMBER;
};
void JSONElement::Set (std::string n, int v) {
name = n;
value = std::to_string(v);
type = JSON_T_NUMBER;
};
void JSONElement::Set (std::string n, int64_t v) {
name = n;
value = std::to_string(v);
type = JSON_T_NUMBER;
};
void JSONElement::Set (std::string n, std::string v) {
name = n;
value = StringAddEscape(&v);
type = JSON_T_STRING;
};
void JSONElement::SetArray (std::string n, std::list<JSONElement> *l) {
std::list<JSONElement>::iterator iter;
name = n;
value = "[";
type = JSON_T_STRING;
for (iter = l->begin(); iter != l->end(); iter++) {
if (iter != l->begin()) value += ",";
value += iter->GetString();
}
value += "]";
};
void JSONElement::SetAddArray (std::string n, std::string jpstring) {
std::size_t ab; // start of array [
std::size_t ae; // end of array ]
if (type != JSON_T_ARRAY || n.compare (name) != 0) {
// reset array
value = "[]";
name = n;
}
type = JSON_T_ARRAY;
ab = value.find_first_of('[');
ae = value.find_last_of(']');
value = value.substr(0, ae);
if (value.length() > 2) value += ",";
value += jpstring + "]";
}
void JSONElement::SetObject (std::string n, std::string s) {
name = n;
value = s;
type = JSON_T_OBJECT;
};
std::string JSONElement::GetString () {
std::string output = "";
std::string filename = __FILE__;
switch (type) {
case(JSON_T_NUMBER):
output += "\"" + name + "\" : " + value;
break;
case(JSON_T_STRING):
if (value.length()==0) {
output += "\"" + name + "\" : \"\"";
}
else if (value[0] != '"') {
output += "\"" + name + "\" : \"" + value + "\"";
}
else output += "\"" + name + "\" : " + value;
break;
case(JSON_T_OBJECT):
output += "\"" + name + "\" : " + value;
break;
case(JSON_T_ARRAY):
if (value.length()==0) {
output += "\"" + name + "\" : []";
}
else if (value[0] != '[') {
output += "\"" + name + "\" : [" + value + "]";
}
else output += "\"" + name + "\" : " + value;
break;
default:
output += "\"error\" : \""+ filename + ":" + std::to_string(__LINE__)
+" JSONElement unknown type error ("+std::to_string(type)+")\"";
break;
}
return output;
};

@ -82,3 +82,17 @@ int file_is_readable (const char *fname) {
return 1;
};
std::string string_to_upper(std::string s) {
for (int i = 0; i < s.length(); i++) s[i] = toupper(s[i]);
return s;
};
std::string string_to_lower(std::string s) {
for (int i = 0; i < s.length(); i++) s[i] = tolower(s[i]);
return s;
};

@ -308,3 +308,59 @@ int SSLSocket::TimeoutTime() {
((tv.tv_usec-timeout_start.tv_usec) / 1000);
};
/// @brief generate an sha256 hash from the giving string
/// @param in string to get an hash sum from
/// @return hashsum
std::string getsha256sum(std::string *in) {
std::string out = "";
EVP_MD_CTX *mdctx;
unsigned char *chksum = NULL;
unsigned int chksumlen;
char hex[] = "0123456789abcdef";
int i;
if (in == NULL) return "";
if ((mdctx = EVP_MD_CTX_create()) == NULL) return "";
if (1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL)) {
EVP_MD_CTX_destroy(mdctx);
return "";
}
if (1 != EVP_DigestUpdate(mdctx, in->c_str(), strlen(in->c_str()))) {
EVP_MD_CTX_destroy(mdctx);
return "";
}
if ((chksum = (unsigned char *)OPENSSL_malloc(EVP_MD_size(EVP_sha256()))) == NULL) {
EVP_MD_CTX_destroy(mdctx);
return "";
}
if (1 != EVP_DigestFinal_ex(mdctx, chksum, &chksumlen)) out = "";
else {
//
// convert data to hex;
for (out = "", i = 0; i < chksumlen; i++) {
unsigned char c = chksum[i];
out += hex[(c >> 4) & 0x0f];
out += hex[c & 0x0f];
}
}
OPENSSL_free (chksum);
EVP_MD_CTX_destroy(mdctx);
return out;
};
std::string getrandomtext(int numbytes) {
std::string text = "";
for (int i = 0; i < numbytes; i++) {
char c = ((rand() % (90-48)) + 48);
text += c;
}
return text;
};

@ -0,0 +1,35 @@
#include <string>
#include "UDPTCPNetwork.h"
int main(int argc, char** argv) {
JSONParse jpa;
JSONParse jp;
JSONElement je;
std::string s = "";
int i, r = 0;
jp.Clear();
jp.AddObject("somestring", "Test \"embedded\" string");
je.Clear();
for (i = 0; i < 4; i++) {
jpa.Clear();
jpa.AddObject("value_i", i);
jpa.AddObject("value_2i", i*2);
je.SetAddArray("testarray", jpa.ToString());
}
jp.AddObject(je);
jp.GetValueString("somestring", &s);
for (r = 1, i = 0; i < 4; i++) {
int a = 0, b = 1;
jpa.Clear();
jp.GetObjectIdx("testarray", i, &jpa);
jpa.GetValueInt("value_i", &a);
jpa.GetValueInt("value_2i", &b);
if (a *2 != b) r = 0;
}
printf ("Test Array: %s\n", r ? (char*)"true" : (char*) "false");
return 0;
};

@ -9,6 +9,20 @@
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
int test_sha256() {
// generated with echo -n topsecret | sha256sum
std::string hash_test = "53336a676c64c1396553b2b7c92f38126768827c93b64d9142069c10eda7a721";
std::string in = "topsecret";
std::string hash = getsha256sum(&in);
if (hash.compare(hash_test) != 0) {
printf ("test for sha256 hash failed. please fix function getsha256sum()\n");
exit (1);
}
else printf ("ok\n");
return 0;
};
void server () {
TCP tcpserver;
TCP *connection;
@ -19,6 +33,13 @@ void server () {
time_t time_now = time (NULL);
char buffer[NET_BUFFERSIZE];
//
// test sha function
if (test_sha256() != 0) {
printf ("getsha256sum - test failed\n");
exit(1);
}
//
// start the server
printf ("server: starting server\n");

@ -1,17 +0,0 @@
#include <string.h>
#include <stdlib.h>
#include "UDPTCPNetwork.h"
int main (int argc, char **argv) {
UDP udp;
char buffer[256] = "Hallo";
udp.Listen(12345);
snprintf (buffer, 256, "ein test, Parameter 0:%s", argv[0]);
udp.Write("www.gulpe.de:12345", buffer, strlen (buffer));
return 0;
};
Loading…
Cancel
Save