From 7da4ffd4cbbd03ea9cc76e70ba634a4d8aceee91 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Thu, 16 Oct 2025 18:56:42 +0200 Subject: [PATCH] adding new functions... --- Makefile | 7 +- README.md | 18 ++ UDPTCPNetwork-json.h | 77 ++++++ UDPTCPNetwork.h | 6 +- json.cc | 605 +++++++++++++++++++++++++++++++++++++++++++ network.cc | 14 + ssl.cc | 56 ++++ test-json.cc | 35 +++ test-ssl.cc | 21 ++ test.cc | 17 -- webserver.cc | 0 11 files changed, 836 insertions(+), 20 deletions(-) create mode 100644 README.md create mode 100644 UDPTCPNetwork-json.h create mode 100644 json.cc create mode 100644 test-json.cc delete mode 100644 test.cc create mode 100644 webserver.cc diff --git a/Makefile b/Makefile index fdd34cb..5758d48 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e441aed --- /dev/null +++ b/README.md @@ -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. diff --git a/UDPTCPNetwork-json.h b/UDPTCPNetwork-json.h new file mode 100644 index 0000000..8fb845e --- /dev/null +++ b/UDPTCPNetwork-json.h @@ -0,0 +1,77 @@ + +#ifndef _JSON_H_ +#define _JSON_H_ + +#include +#include +#include + +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 *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 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 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_ diff --git a/UDPTCPNetwork.h b/UDPTCPNetwork.h index 89c8677..65af24d 100644 --- a/UDPTCPNetwork.h +++ b/UDPTCPNetwork.h @@ -40,6 +40,7 @@ #endif +#include "UDPTCPNetwork-json.h" #include #include @@ -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 diff --git a/json.cc b/json.cc new file mode 100644 index 0000000..f97af21 --- /dev/null +++ b/json.cc @@ -0,0 +1,605 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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::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::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::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::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 JSONParse::GetElements() { + std::list l; + std::list::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::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 *l) { + std::list::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; +}; + diff --git a/network.cc b/network.cc index 6c26230..e9a8a11 100644 --- a/network.cc +++ b/network.cc @@ -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; +}; + + + diff --git a/ssl.cc b/ssl.cc index 05bb78e..aff56e5 100644 --- a/ssl.cc +++ b/ssl.cc @@ -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; +}; + diff --git a/test-json.cc b/test-json.cc new file mode 100644 index 0000000..971ad53 --- /dev/null +++ b/test-json.cc @@ -0,0 +1,35 @@ + +#include +#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; +}; diff --git a/test-ssl.cc b/test-ssl.cc index bf4c82f..2be2f6f 100644 --- a/test-ssl.cc +++ b/test-ssl.cc @@ -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"); diff --git a/test.cc b/test.cc deleted file mode 100644 index 2d104be..0000000 --- a/test.cc +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include -#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; -}; - diff --git a/webserver.cc b/webserver.cc new file mode 100644 index 0000000..e69de29