1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
17 #include <sys/types.h>
19 #include <sys/utsname.h>
20 #include <arpa/inet.h>
21 #include <sys/socket.h> // extraccion de IP del hostname
22 #include <netinet/in.h> // extraccion de IP del hostname
23 #include <netdb.h> // extraccion de IP del hostname
24 #include <unistd.h> // gethostname
26 #include <anna/core/functions.hpp>
27 #include <anna/core/DataBlock.hpp>
28 #include <anna/core/tracing/Logger.hpp>
29 #include <anna/core/util/Second.hpp>
30 #include <anna/core/util/Tokenizer.hpp>
38 #define PAGE_WIDTH_LENGTH 80
40 string functions::getVersion() throw() {
41 static const int version = ANNA_VERSION;
43 int mainVersion = (version & 0xff00) >> 8;
44 int subVersion = (version & 0xff);
46 sprintf(aux, "%d.%d", mainVersion, subVersion);
48 return result += getArchitecture();
52 (1) Solo coge los dos primeros digitos del numero de release
54 string functions::getArchitecture() throw() {
56 WHEN_MULTITHREAD(result = "/MT");
57 WHEN_SINGLETHREAD(result = "/ST");
71 char* release = anna_strchr(un.release, '.'); // (1)
74 if((release = anna_strchr(release + 1, '.')) != NULL)
84 string functions::asString(const int number)
87 sprintf(aux, "%d", number);
91 string functions::asString(const S64 number)
94 //sprintf(aux, "%lld", number);
96 sprintf (aux, "%ld", number);
98 sprintf (aux, "%lld", number);
103 string functions::asString(const unsigned int number)
106 sprintf(aux, "%u", number);
110 string functions::asString(const U64 number)
113 //sprintf(aux, "%llu", number);
115 sprintf (aux, "%lu", number);
117 sprintf (aux, "%llu", number);
122 string functions::asString(const float number, const char* format)
125 sprintf(aux, format, number);
129 string functions::asString(const double number, const char* format)
132 sprintf(aux, format, number);
136 string functions::asDateTime(const Second &second)
138 char aux [DateTimeSizeString];
139 return std::string(asDateTime(second, aux));
142 const char* functions::asDateTime(const Second &second, char* result)
144 struct tm* tt = localtime((time_t*) & second);
146 result, "%02d/%02d/%4d %02d:%02d:%02d",
147 tt->tm_mday, tt->tm_mon + 1, tt->tm_year + 1900,
148 tt->tm_hour, tt->tm_min, tt->tm_sec
153 std::string functions::asString(const DataBlock& dataBlock, const int characterByLine)
155 return dataBlock.asString(characterByLine);
158 string functions::asHexString(const int number)
161 sprintf(aux, "0x%x", number);
165 string functions::asHexString(const S64 number)
168 //sprintf(aux, "0x%llx", number);
170 sprintf (aux, "0x%lx", number);
172 sprintf (aux, "0x%llx", number);
177 // from a version by Allen Holub (see Andrew Binstock, "Hashing Revisited"
178 // Dr. Dobb's Journal, April 1996)
179 S64 functions::hash(const char* p)
181 static const int long_bits = sizeof(S64) << 3;
182 static const int one_eighth = long_bits >> 3;
183 static const int three_fourths = long_bits * 3 / 4;
184 static const S64 high_bits = ((S64)(~0L)) << (long_bits - one_eighth);
189 result = (result << one_eighth) + *p ++;
191 if((temp = result & high_bits) != 0)
192 result = (result ^(temp >> three_fourths)) &~ high_bits;
199 std::string functions::asHexString(const DataBlock& dataBlock)
201 const char* buffer = dataBlock.getData();
202 const int size = dataBlock.getSize();
206 for(int ii = 0; ii < size; ii ++) {
207 byte = (buffer [ii] & 0xf0) >> 4;
208 result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
209 byte = (buffer [ii] & 0x0f);
210 result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
217 * Gets the original value obtained with #asHexString (const DataBlock&).
218 * \param hexString String which contains the buffer. The format is an hexadecimal octet sequence representation (i.e. 'af012fb3', with even number of digits).
219 * The input shall be preprocessed to comply with that format (e.g. colon or any other non-hex digit must be removed).
220 * \param target DataBlock for string decode.
221 * \return DataBlock corresponding to the provided string.
224 DataBlock& functions::fromHexString(const std::string& hexString, DataBlock& target)
225 throw(RuntimeException) {
227 if((hexString.length() % 2) != 0)
228 throw RuntimeException("functions::fromHexString | Invalid string length", ANNA_FILE_LOCATION);
231 const char* src = hexString.data();
235 for(int ii = 1, maxii = hexString.length(); ii < maxii; ii += 2) {
236 if(isxdigit(aux = src [ii - 1]) == 0)
237 throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
239 hex = ((aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a)) << 4;
241 if(isxdigit(aux = src [ii]) == 0)
242 throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
244 hex |= (aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a);
251 string functions::asString(const char* format, ...)
255 va_start(ap, format);
256 vsnprintf(aux, sizeof(aux), format, ap);
261 void functions::sleep(const Millisecond &millisecond)
265 req.tv_sec = millisecond.getValue() / 1000; // segundos
266 req.tv_nsec = (millisecond.getValue() % 1000); // milisegundos
267 req.tv_nsec *= 1000000; // mili = 10e-3, nano=10-9
270 while((r = nanosleep(&req, &rem)) != 0) {
274 string msg(asText("functions::sleep | timespec { sec: ", (int) req.tv_sec));
275 msg += functions::asText("| nsec: ", (int) req.tv_nsec);
277 RuntimeException ex(msg, errno, ANNA_FILE_LOCATION);
284 bool functions::asBool(const char* str)
285 throw(RuntimeException) {
289 if(strcasecmp(str, "true") == 0 || anna_strcmp(str, "1") == 0)
292 if(strcasecmp(str, "false") == 0 || anna_strcmp(str, "0") == 0)
295 string msg("anna::funcions::asBool | Cannot interpret '");
297 msg += "' as boolean";
298 throw RuntimeException(msg, ANNA_FILE_LOCATION);
301 S64 functions::asInteger64(const char* str)
304 //sscanf(str, "%lld", &number);
306 sscanf (str, "%ld", &number);
308 sscanf (str, "%lld", &number);
313 pthread_t functions::getCurrentThread()
315 WHEN_MULTITHREAD(return pthread_self());
316 WHEN_SINGLETHREAD(return 0);
319 bool functions::isLike(const char* pattern, const std::string& _value)
320 throw(RuntimeException) {
321 const char* value = _value.c_str();
325 if((ret = regcomp(&preg, pattern, REG_EXTENDED)) != 0) {
327 string msg("anna::functions::isLike | ");
328 msg += " | Pattern: ";
334 if(regerror(ret, &preg, err, sizeof(err)))
337 msg += "Invalid pattern";
339 throw RuntimeException(msg, ANNA_FILE_LOCATION);
342 const bool result = (regexec(&preg, value, 0, NULL, 0) == 0) ? true : false;
349 S64 functions::merge(const char* whatis, const int n1, const int n2, const int bitShift)
350 throw(RuntimeException) {
351 if(bitShift > intBitSize) {
352 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | bitShift must be less than %d", whatis, n1, n2, bitShift, intBitSize));
353 throw RuntimeException(msg, ANNA_FILE_LOCATION);
356 if((bitsize(n1) + bitShift) > int64BitSize) {
357 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N1 overload", whatis, n1, n2, bitShift));
358 throw RuntimeException(msg, ANNA_FILE_LOCATION);
361 if(bitsize(n2) > bitShift) {
362 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N2 overload", whatis, n1, n2, bitShift));
363 throw RuntimeException(msg, ANNA_FILE_LOCATION);
370 if(bitShift == intBitSize) {
372 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | ", whatis, n1, n2, bitShift));
373 msg += functions::asHexString(result);
374 Logger::information(msg, ANNA_FILE_LOCATION);
383 * Basado en el algoritmo de http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
385 int functions::log2(const unsigned int v)
387 static const signed char LogTable256[] = {
388 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
389 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
390 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
391 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
392 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
393 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
394 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
395 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
396 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
397 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
398 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
399 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
400 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
401 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
402 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
403 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
405 int r = -1; // r will be lg(v)
406 unsigned int t, tt; // temporaries
409 r = ((t = tt >> 8)) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
411 r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
417 std::string functions::entriesAsString(int number, const char * wordForSingular, const char * wordForPlural) throw() {
419 std::string singular = (wordForSingular ? wordForSingular : "entry");
420 std::string plural = (wordForPlural ? wordForPlural : "entries");
422 if(wordForSingular && !wordForPlural)
423 plural = singular + "s";
425 result += ((number != 0) ? anna::functions::asString(number) : "no");
427 result += ((number != 1) ? plural : singular);
432 std::string functions::justify(const std::string & title, TextJustifyMode::_v mode, char filler) throw() {
434 int d_size = title.size();
435 int repeat = PAGE_WIDTH_LENGTH - d_size - 1;
438 if(mode == TextJustifyMode::Center) {
439 repeat = (repeat - 1) / 2;
440 adjust = (2 * (repeat + 1) + d_size != PAGE_WIDTH_LENGTH);
443 if((mode == TextJustifyMode::Right) || (mode == TextJustifyMode::Center)) {
444 for(int k = 0; k < (repeat + (adjust ? 1 : 0)); k++) result += filler;
451 if((mode == TextJustifyMode::Left) || (mode == TextJustifyMode::Center)) {
454 for(int k = 0; k < repeat; k++) result += filler;
461 std::string functions::highlight(const std::string & title, TextHighlightMode::_v mode, char filler, bool appendCR) throw() {
463 int ou_repeat = title.size();
464 int lr_repeat = PAGE_WIDTH_LENGTH - ou_repeat - 1;
467 if(mode == TextHighlightMode::LeftAndRightline) {
468 lr_repeat = (lr_repeat - 1) / 2;
469 adjust = (2 * (lr_repeat + 1) + ou_repeat != PAGE_WIDTH_LENGTH);
472 if((mode == TextHighlightMode::Leftline) || (mode == TextHighlightMode::LeftAndRightline)) {
473 for(int k = 0; k < (lr_repeat + (adjust ? 1 : 0)); k++) result += filler;
478 if((mode == TextHighlightMode::Overline) || (mode == TextHighlightMode::OverAndUnderline)) {
479 for(int k = 0; k < ou_repeat; k++) result += filler;
486 if((mode == TextHighlightMode::Underline) || (mode == TextHighlightMode::OverAndUnderline)) {
489 for(int k = 0; k < ou_repeat; k++) result += filler;
492 if((mode == TextHighlightMode::Rightline) || (mode == TextHighlightMode::LeftAndRightline)) {
495 for(int k = 0; k < lr_repeat; k++) result += filler;
498 if(appendCR) result += "\n";
504 std::string functions::tab(const std::string & text, int tabSpaces) throw() {
506 size_t pos, from = 0;
507 std::string tab, crTab = "\n";
509 for(int k = 0; k < tabSpaces; k++) tab += " ";
515 while(((pos = result.find('\n', from)) != std::string::npos) && (pos != (result.size() - 1)/*exclude last CR if exists*/)) {
516 result.replace(pos, 1, crTab);
524 bool functions::endsWith(const std::string & pattern, const std::string & suffix, std::string & preffix) throw() {
527 if(pattern.size() < suffix.size()) return false;
529 size_t pos = pattern.rfind(suffix);
531 if(pos == std::string::npos) return false;
533 preffix.assign(pattern.c_str(), pos);
534 return (pos == (pattern.size() - suffix.size()));
538 bool functions::startsWith(const std::string & pattern, const std::string & preffix, std::string & suffix) throw() {
541 if(pattern.size() < preffix.size()) return false;
543 if(pattern.find(preffix) != 0) return false;
545 suffix.assign(pattern.c_str(), preffix.size(), pattern.size() - preffix.size());
550 std::string functions::replace(const std::string & text, const char *item, const char *target, bool all) throw() {
551 std::string result = text;
553 if(!item || !target) return result; // protection for NULL strings provided
555 size_t lengthReplaced = strlen(item);
556 size_t pos = result.find(item);
558 while(pos != std::string::npos) {
559 result.replace(pos, lengthReplaced, target);
563 pos = result.find(item);
570 std::string functions::addQuotationMarks(const std::string & str) throw() {
571 std::string result = "'";
578 std::string functions::addQuotationMarks(const char * str) throw() {
579 std::string result = "'";
580 result += (str ? str : "<null>");
586 std::string functions::addQuotationMarks(const int & integer) throw() {
587 std::string result = "'";
588 result += anna::functions::asString(integer);
594 std::string functions::vectorToStringRepresentation(const std::vector<int> & v, const char separator) throw() {
595 std::string result = "";
598 std::vector<int>::const_iterator iter;
599 std::vector<int>::const_iterator iter_min(v.begin());
600 std::vector<int>::const_iterator iter_max(v.end());
602 for(iter = iter_min; iter != iter_max; iter++) {
603 result += anna::functions::asString(*iter);
607 // Delete the last space: starts at 'size()-1', take 1 caracter:
608 result.erase(result.size() - 1, 1);
615 std::string functions::vectorToStringRepresentation(const std::vector<std::string> & v, const char separator) throw() {
616 std::string result = "";
619 std::vector<std::string>::const_iterator iter;
620 std::vector<std::string>::const_iterator iter_min(v.begin());
621 std::vector<std::string>::const_iterator iter_max(v.end());
623 for(iter = iter_min; iter != iter_max; iter++) {
628 // Delete the last space: starts at 'size()-1', take 1 caracter:
629 result.erase(result.size() - 1, 1);
636 std::string functions::socketLiteralAsString(const std::string & address, int port) throw() {
637 std::string result = address;
639 result += anna::functions::asString(port);
644 std::string functions::asAsciiString(const char * buffer, int size, bool & isFullyPrintable) throw() {
646 // Supposed printable by default:
647 isFullyPrintable = true;
649 if(size == 0 || !buffer) {
651 isFullyPrintable = false;
655 for(int k = 0; k < size; k ++) {
656 unsigned char c = (unsigned char) buffer [k];
657 int printable = isprint(c);
658 result += (printable ? (char) c : '.');
660 if(!printable) isFullyPrintable = false;
667 std::string functions::getHostname() throw() {
669 std::string result = "<hostname>";
671 if(gethostname(aux, sizeof aux) == 0 /*success*/)
677 std::string functions::getDomainname() throw() {
679 std::string result = "<domainname>";
681 if(getdomainname(aux, sizeof aux) == 0 /*success*/)
687 std::string functions::getFQDN(const char *hostname, const char *domainname) throw() {
688 std::string hn = hostname ? hostname : (functions::getHostname());
689 std::string dn = domainname ? domainname : (functions::getDomainname());
690 // FQDN is limited to 255 bytes, with aditional restriction: 63 bytes label within a domain name.
692 if(hn == "") return dn;
694 if(dn == "") return hn;
696 std::string label(hn, 0, 63);
697 std::string fqdn(label + "." + dn, 0, 255);
701 std::string functions::getHostnameIP() throw() {
702 std::string result = "";
704 struct in_addr **addr_list;
706 gethostname(hostname, sizeof hostname);
708 if((he = gethostbyname(hostname)) != NULL) {
709 // Official name: he->h_name
711 addr_list = (struct in_addr **)he->h_addr_list;
713 for(int i = 0; addr_list[i] != NULL; i++) {
714 //printf("%s ", inet_ntoa(*addr_list[i]));
715 result = inet_ntoa(*addr_list[i]);
724 anna::DataBlock functions::rawIpPresentationAsRaw(const std::string & rawPresentation) throw(anna::RuntimeException) {
725 int length = rawPresentation.size();
727 if(length != 8 && length != 32)
728 throw anna::RuntimeException("functions::rawIpPresentationAsRaw | Expected 8 or 32-sized raw IP presentation provided", ANNA_FILE_LOCATION);
730 anna::DataBlock result(true);
732 char rByte[3]; // readable byte
735 for(int k = 0; k < length; k += 2) {
736 rByte[0] = rawPresentation[k];
737 rByte[1] = rawPresentation[k + 1];
738 sscanf(rByte, "%x", &byte);
746 std::string functions::rawIpAsRawIpPresentation(const anna::DataBlock & db) throw(anna::RuntimeException) {
747 int length = db.getSize();
749 if(length != 4 && length != 16)
750 throw anna::RuntimeException("functions::rawIpAsRawIpPresentation | Expected 4 or 16-sized raw IP DataBlock provided", ANNA_FILE_LOCATION);
752 std::string result = "";
754 char rByte[3]; // readable byte
757 for(int k = 0; k < length; k++) {
758 byte = (unsigned char)db[k];
759 sprintf(rByte, "%.2X", byte);
771 // IPv6 addresses have two logical parts: a 64-bit network prefix, and a 64-bit host address part. (The host address is often automatically generated from the interface MAC address.[34]) An IPv6 address is represented by 8 groups of 16-bit hexadecimal values separated by colons (:) shown as follows:
772 // A typical example of an IPv6 address is
773 // 2001:0db8:85a3:0000:0000:8a2e:0370:7334
774 // The hexadecimal digits are case-insensitive.
776 // The 128-bit IPv6 address can be abbreviated with the following rules:
777 // -Rule one: Leading zeroes within a 16-bit value may be omitted. For example, the address fe80:0000:0000:0000:0202:b3ff:fe1e:8329 may be written as fe80:0:0:0:202:b3ff:fe1e:8329
778 // -Rule two: A single occurrence of consecutive groups of zeroes within an address may be replaced by a double colon. For example, fe80:0:0:0:202:b3ff:fe1e:8329 becomes fe80::202:b3ff:fe1e:8329
779 // A single IPv6 address can be represented in several different ways, such as 2001:db8::1:0:0:1 and 2001:0DB8:0:0:1::1. RFC 5952 recommends a canonical textual representation.
781 // Si la dirección tiene más de una serie de grupos nulos consecutivos la compresión sólo se permite en uno de ellos.
782 // AsÃ, las siguientes son representaciones posibles de una misma dirección:
784 // 2001:0DB8:0000:0000:0000:0000:1428:57ab
785 // 2001:0DB8:0000:0000:0000::1428:57ab
786 // 2001:0DB8:0:0:0:0:1428:57ab
787 // 2001:0DB8:0::0:1428:57ab
788 // 2001:0DB8::1428:57ab
789 // son todas válidas y significan lo mismo, pero
792 // no es válida porque no queda claro cuántos grupos nulos hay en cada lado.
794 // Los ceros iniciales en un grupo también se pueden omitir:
795 // 2001:0DB8:02de::0e13
798 // Si la dirección es una dirección IPv4 empotrada (mapped), los últimos 32 bits pueden escribirse en base decimal, asÃ:
799 // ::ffff:192.168.89.9
802 // No se debe confundir con:
806 // El formato ::ffff:1.2.3.4 se denomina dirección IPv4 mapeada, y el formato ::1.2.3.4 dirección IPv4 compatible.
807 // Las direcciones IPv4 pueden ser transformadas fácilmente al formato IPv6. Por ejemplo, si la dirección decimal IPv4 es 135.75.43.52
808 // (en hexadecimal, 0x874B2B34), puede ser convertida a 0000:0000:0000:0000:0000:0000:874B:2B34 o ::874B:2B34. Entonces, uno puede usar
809 // la notación mixta dirección IPv4 compatible, en cuyo caso la dirección deberÃa ser ::135.75.43.52. Este tipo de dirección IPv4 compatible
810 // casi no está siendo utilizada en la práctica, aunque los estándares no la han declarado obsoleta.
812 // http://tools.ietf.org/html/rfc5952: canonical text representation recommendation
814 bool functions::isIPv4(const std::string & ip, IPv4Type::_v ipv4Type) throw() {
815 if(ipv4Type == IPv4Type::Estrict) {
816 // La expresión regular no controla si hay mas de 3 puntos:
819 for(int k = 0; k < ip.length(); k++)
820 if(ip[k] == '.') n_dot++;
825 bool ipv4 = anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, ip);
826 bool colon = (ip.find(":") != std::string::npos);
827 return (ipv4 && !colon);
830 if(ipv4Type == IPv4Type::Compatible) {
831 std::string pureIPv4 = ip;
832 bool firstDoubleColon = (ip.find("::") == 0);
834 if(firstDoubleColon) {
835 pureIPv4.erase(0, 2);
836 bool anotherColon = (pureIPv4.find(":") != std::string::npos);
838 if(anotherColon) return (false);
840 return (anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, pureIPv4));
844 if(ipv4Type == IPv4Type::Mapped) {
845 size_t posLastColon = ip.rfind(":");
847 if(posLastColon == std::string::npos)
850 if(!isIPv4(ip.substr(posLastColon + 1)))
853 unsigned char buf[sizeof(struct in6_addr)];
854 int s = inet_pton(AF_INET6, ip.c_str(), buf);
864 bool functions::isIPv6(const std::string & ip) throw() {
865 // Chequeo de digitos permitidos:
866 for(int k = 0; k < ip.length(); k++) {
867 bool digit = isdigit(ip[k]);
868 bool hex = ((ip[k] == 'a') ||
880 bool colon = (ip[k] == ':');
882 if(!digit && !hex && !colon)
886 return (anna::functions::isLike(s_REGEXP_IPv6_ADDRESSES, ip));
890 std::string functions::IPv4To6(const std::string & ip) throw(anna::RuntimeException) {
891 if(!isIPv4(ip, IPv4Type::Estrict) && !isIPv4(ip, IPv4Type::Compatible) && !isIPv4(ip, IPv4Type::Mapped))
892 throw anna::RuntimeException("functions::IPv4To6 | Expected IPv4, IPv4-compatible or IPv4-mapped address format", ANNA_FILE_LOCATION);
894 std::string result, pureIPv4;
895 bool firstDoubleColon = (ip.find("::") == 0);
897 if(firstDoubleColon) {
899 size_t ipv4_pos = ip.rfind(":") /* last ocurrence */ + 1;
900 pureIPv4 = ip.substr(ipv4_pos);
903 size_t posColon = ip.find(":");
905 if(posColon == 0) // first colon
906 throw anna::RuntimeException("functions::IPv4To6 | Invalid IPv4 address format", ANNA_FILE_LOCATION);
908 if(posColon != std::string::npos) // any colon
909 return ip; // seems to be IPv6 already?
911 throw anna::RuntimeException("functions::IPv4To6 | Unreconized IPv4 address format", ANNA_FILE_LOCATION);
917 // Number of ocurrences for '.'
920 for(int k = 0; k < pureIPv4.length(); k++)
921 if(pureIPv4[k] == '.') n_dot++;
924 throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (more than three dots!)", ANNA_FILE_LOCATION);
927 anna::Tokenizer::const_iterator tok_it;
929 tok.apply(pureIPv4, ".");
933 for(tok_it = tok.begin(); tok_it != tok.end(); tok_it ++) {
934 token = anna::Tokenizer::data(tok_it);
935 v[cnt] = atoi(anna::Tokenizer::data(tok_it));
937 if(v[cnt] < 0 || v[cnt] > 255)
938 throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (any value out of range 0-255)", ANNA_FILE_LOCATION);
943 if(isIPv4(ip, IPv4Type::Compatible))
944 result = anna::functions::asString("::%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
946 result = anna::functions::asString("::ffff:%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
952 std::string functions::normalizeIP(const std::string & ip) throw(anna::RuntimeException) {
953 std::string result = ip;
954 // std::transform(result.begin(), result.end(), result.begin(), (int (*)(int))std::tolower);
955 std::transform(result.begin(), result.end(), result.begin(), ::tolower);
957 if(isIPv4(ip, IPv4Type::Estrict) || isIPv4(ip, IPv4Type::Compatible) || isIPv4(ip, IPv4Type::Mapped))
958 result = IPv4To6(result);
960 size_t pos = result.find("::"); // zeroes simplification group
961 size_t rpos = result.rfind("::"); // zeroes simplification group
964 throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (more than one simplification group '::')", ANNA_FILE_LOCATION);
966 if(pos != std::string::npos) { // zeroes exists
967 // string ( size_t n, char c ) -> content is initialized as a string formed by a repetition of character c, n times.
968 // Number of ocurrences for ':'
971 for(int k = 0; k < result.length(); k++)
972 if(result[k] == ':') n_colon++;
974 // Generate equivalent to '::'
975 std::string equiv_str;
977 for(int k = 0; k < (8 - n_colon); k++)
981 // Replace with equivalent:
982 result.replace(pos, 2, equiv_str);
984 // Special case: IP began with '::'
985 if(result[0] == ':') {
986 result.insert(0, "0");
989 // Special case: IP was only '::'
990 if(result[result.length() - 1] == ':') {
995 // Protection: it must be seven colons:
998 for(int k = 0; k < result.length(); k++)
999 if(result[k] == ':') n_colon++;
1002 throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (missing any 16-bit group)", ANNA_FILE_LOCATION);
1004 // Padding with zeroes at left
1005 anna::Tokenizer ipStr;
1006 anna::Tokenizer::const_iterator ipStr_it;
1008 ipStr.apply(result, ":");
1011 for(ipStr_it = ipStr.begin(); ipStr_it != ipStr.end(); ipStr_it ++) {
1012 token = anna::Tokenizer::data(ipStr_it);
1014 while(token.length() < 4) token.insert(0, "0");
1021 size_t lastPos = result.length() - 1;
1022 result.erase(lastPos, 1);
1024 // Chequeo de digitos permitidos:
1025 for(int k = 0; k < result.length(); k++) {
1026 bool digit = isdigit(result[k]);
1027 bool hex = ((result[k] == 'a') ||
1028 (result[k] == 'b') ||
1029 (result[k] == 'c') ||
1030 (result[k] == 'd') ||
1031 (result[k] == 'e') ||
1032 (result[k] == 'f'));
1033 bool colon = (result[k] == ':');
1035 if(!digit && !hex && !colon) {
1036 throw anna::RuntimeException("functions::normalizeIP | Invalid address format (only digits (0-9) and hex digits are allowed)", ANNA_FILE_LOCATION);
1044 bool functions::sameIP(const std::string & ip1, const std::string & ip2) throw(anna::RuntimeException) {
1045 //if (ip1 == ip2) return true; it should validate wrong-format addresses
1046 return (normalizeIP(ip1) == normalizeIP(ip2));
1050 bool functions::matchIPv6(const std::string & _ipv6, const std::string & preffixedIpv6) throw(anna::RuntimeException) {
1051 size_t preffixPos = preffixedIpv6.find("/");
1053 if(preffixPos == std::string::npos)
1054 return (sameIP(_ipv6, preffixedIpv6));
1056 std::string ipv6 = _ipv6;
1058 if(isIPv4(_ipv6, IPv4Type::Estrict) || isIPv4(_ipv6, IPv4Type::Compatible) || isIPv4(_ipv6, IPv4Type::Mapped)) ipv6 = IPv4To6(_ipv6);
1060 std::string _ipv6_2 = preffixedIpv6.substr(0, preffixPos);
1061 std::string ipv6_2 = _ipv6_2;
1063 if(isIPv4(_ipv6_2, IPv4Type::Estrict) || isIPv4(_ipv6_2, IPv4Type::Compatible) || isIPv4(_ipv6_2, IPv4Type::Mapped)) ipv6_2 = IPv4To6(_ipv6_2);
1065 std::string preffix = preffixedIpv6.substr(preffixPos + 1);
1066 int ipv6_2_preffixLength = atoi(preffix.c_str());
1068 if(ipv6_2_preffixLength < 0 || ipv6_2_preffixLength > 128)
1069 throw anna::RuntimeException("functions::matchIPv6 | Invalid Ipv6 preffix length: out of range [0,128]", ANNA_FILE_LOCATION);
1071 // No restriction, all ipv6_2 ignored (special and not usual case)
1072 if(ipv6_2_preffixLength == 0) return true;
1075 int spare = ipv6_2_preffixLength /* bits */ % 8; // bytes
1076 int incompletedRestrictionBytes = ipv6_2_preffixLength / 8;
1077 int completedRestrictionBytes = incompletedRestrictionBytes + ((spare != 0) ? 1 : 0);
1078 char mask = 0xFF << (8 - spare);
1080 anna::DataBlock rawIP1 = ipAsRaw(ipv6);
1081 anna::DataBlock restrictedIP1(true);
1082 restrictedIP1.assign(rawIP1.getData(), incompletedRestrictionBytes);
1084 if(spare != 0) restrictedIP1 += rawIP1[incompletedRestrictionBytes] & mask;
1087 anna::DataBlock rawIP2 = ipAsRaw(ipv6_2);
1088 anna::DataBlock realIP2(true);
1089 realIP2.assign(rawIP2.getData(), incompletedRestrictionBytes);
1091 if(spare != 0) realIP2 += rawIP2[incompletedRestrictionBytes] & mask;
1094 int n = memcmp(restrictedIP1.getData(), realIP2.getData(), completedRestrictionBytes);
1099 anna::DataBlock functions::ipAsRaw(const std::string & ip) throw(anna::RuntimeException) {
1100 anna::DataBlock result(true);
1103 unsigned char buf[sizeof(struct in6_addr)];
1104 int s = inet_pton(AF_INET, ip.c_str(), buf);
1107 result += (S8)buf[0];
1108 result += (S8)buf[1];
1109 result += (S8)buf[2];
1110 result += (S8)buf[3];
1112 if(s < 0) perror("inet_pton");
1114 throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv4 address format", ANNA_FILE_LOCATION);
1117 unsigned char buf[sizeof(struct in6_addr)];
1118 int s = inet_pton(AF_INET6, ip.c_str(), buf);
1121 result += (S8)buf[0];
1122 result += (S8)buf[1];
1123 result += (S8)buf[2];
1124 result += (S8)buf[3];
1125 result += (S8)buf[4];
1126 result += (S8)buf[5];
1127 result += (S8)buf[6];
1128 result += (S8)buf[7];
1129 result += (S8)buf[8];
1130 result += (S8)buf[9];
1131 result += (S8)buf[10];
1132 result += (S8)buf[11];
1133 result += (S8)buf[12];
1134 result += (S8)buf[13];
1135 result += (S8)buf[14];
1136 result += (S8)buf[15];
1138 if(s < 0) perror("inet_pton");
1140 throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv6 address format", ANNA_FILE_LOCATION);
1146 // anna::DataBlock result(true);
1149 // if (isIPv4(ip)) {
1151 // int dec1, dec2, dec3, dec4; // U32 type is valid, 'int' better: argument for %d must be 'int *' (http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/)
1152 // sscanf(ip.c_str(), "%d.%d.%d.%d", &dec1, &dec2, &dec3, &dec4);
1153 // result += (S8)dec1;
1154 // result += (S8)dec2;
1155 // result += (S8)dec3;
1156 // result += (S8)dec4;
1160 // int hex1, hex2, hex3, hex4, hex5, hex6, hex7, hex8; // U16 type is not valid: argument for %X must be 'int *' (http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/)
1161 // sscanf(normalizeIP(ip).c_str(), "%X:%X:%X:%X:%X:%X:%X:%X", &hex1, &hex2, &hex3, &hex4, &hex5, &hex6, &hex7, &hex8);
1162 // result += ((S8)(hex1 >> 8));
1163 // result += ((S8)(hex1 & 0x00FF));
1164 // result += ((S8)(hex2 >> 8));
1165 // result += ((S8)(hex2 & 0x00FF));
1166 // result += ((S8)(hex3 >> 8));
1167 // result += ((S8)(hex3 & 0x00FF));
1168 // result += ((S8)(hex4 >> 8));
1169 // result += ((S8)(hex4 & 0x00FF));
1170 // result += ((S8)(hex5 >> 8));
1171 // result += ((S8)(hex5 & 0x00FF));
1172 // result += ((S8)(hex6 >> 8));
1173 // result += ((S8)(hex6 & 0x00FF));
1174 // result += ((S8)(hex7 >> 8));
1175 // result += ((S8)(hex7 & 0x00FF));
1176 // result += ((S8)(hex8 >> 8));
1177 // result += ((S8)(hex8 & 0x00FF));
1185 std::string functions::rawIpAsString(const char *buffer, int bufferLength, bool normalize) throw(anna::RuntimeException) {
1186 std::string result = "";
1187 char str[INET6_ADDRSTRLEN];
1189 if(bufferLength == 4) {
1190 if(inet_ntop(AF_INET, buffer, str, INET_ADDRSTRLEN) != NULL)
1192 } else if(bufferLength == 16) {
1193 if(inet_ntop(AF_INET6, buffer, str, INET6_ADDRSTRLEN) != NULL)
1196 throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1199 throw anna::RuntimeException("functions::rawIpAsString | Wrong IP address serialization (check range value)", ANNA_FILE_LOCATION);
1201 return (normalize ? normalizeIP(result) : result);
1203 // std::string result;
1206 // if (bufferLength == 4) { // IPv4
1207 // result = anna::functions::asString("%d.%d.%d.%d", (U8)buffer[0], (U8)buffer[1], (U8)buffer[2], (U8)buffer[3]);
1209 // else if (bufferLength == 16) { // IPv6
1210 // result = anna::functions::asString("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
1211 // ((((U8)buffer[0]) << 8) & 0xFF00 /* same as (U16 cast)*/) +
1212 // (((U8)buffer[1]) & 0x00FF),
1213 // ((((U8)buffer[2]) << 8) & 0xFF00) +
1214 // (((U8)buffer[3]) & 0x00FF),
1215 // ((((U8)buffer[4]) << 8) & 0xFF00) +
1216 // (((U8)buffer[5]) & 0x00FF),
1217 // ((((U8)buffer[6]) << 8) & 0xFF00) +
1218 // (((U8)buffer[7]) & 0x00FF),
1219 // ((((U8)buffer[8]) << 8) & 0xFF00) +
1220 // (((U8)buffer[9]) & 0x00FF),
1221 // ((((U8)buffer[10]) << 8) & 0xFF00) +
1222 // (((U8)buffer[11]) & 0x00FF),
1223 // ((((U8)buffer[12]) << 8) & 0xFF00) +
1224 // (((U8)buffer[13]) & 0x00FF),
1225 // ((((U8)buffer[14]) << 8) & 0xFF00) +
1226 // (((U8)buffer[15]) & 0x00FF));
1229 // throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1232 // return (normalize ? normalizeIP(result):result);
1236 void functions::getAddressAndPortFromSocketLiteral(const std::string &literal, std::string &address, int &port) throw() {
1237 size_t pos = literal.find_last_of(":");
1238 size_t lastPos = literal.size() - 1;
1239 address = ""; port = -1; // assume error
1241 if((pos != std::string::npos) && (pos != lastPos)) {
1242 address = literal.substr(0, pos);
1243 port = atoi(literal.substr(pos + 1, lastPos).c_str());
1248 socket_v functions::getSocketVectorFromString(const std::string & list) throw() {
1250 std::string address;
1252 anna::Tokenizer lst;
1253 lst.apply(list, ",");
1255 if(lst.size() < 1) return result;
1257 anna::Tokenizer::const_iterator tok_min(lst.begin());
1258 anna::Tokenizer::const_iterator tok_max(lst.end());
1259 anna::Tokenizer::const_iterator tok_iter;
1261 for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) {
1262 getAddressAndPortFromSocketLiteral(anna::Tokenizer::data(tok_iter), address, port);
1264 if(port == -1) { result.clear(); return result; }
1266 result.push_back(socket_t(address, port));
1272 std::string functions::socketVectorAsString(const socket_v & socketVector) throw() {
1275 socket_v_it it_min(socketVector.begin());
1276 socket_v_it it_max(socketVector.end());
1278 for(it = it_min; it != it_max; it++) {
1279 result += anna::functions::asString("%s:%d,", (*it).first.c_str(), (*it).second);
1282 result.erase(result.size() - 1, 1); // remove last comma
1286 bool functions::littleEndian()
1289 char *p = (char *) &i;
1290 if (p[0] == 1) return true;
1294 const char* functions::codeInteger(char* result, const int n)
1297 char* w((char*) &aux);
1299 *(result + 1) = *(w + 1);
1300 *(result + 2) = *(w + 2);
1301 *(result + 3) = *(w + 3);
1305 const char* functions::codeShort(char* result, const short int n)
1307 short int aux(htons(n));
1308 char* w((char*) &aux);
1310 *(result + 1) = *(w + 1);
1314 const char* functions::codeInteger64(char* result, const S64 n)
1316 S64 aux(0xffffffff);
1320 n2 = (aux >> 32) & 0xffffffff;
1321 codeInteger(result, n2);
1322 n2 = n & 0xffffffff;
1323 codeInteger(result + sizeof(int), n2);
1328 const char* functions::codeFloat(char* result, const float n)
1331 anna_memcpy(&ii, &n, sizeof(n));
1332 return functions::codeInteger(result, ii);
1336 const char* functions::codeDouble(char* result, const double n)
1339 anna_memcpy(&ii, &n, sizeof(n));
1340 return functions::codeInteger64(result, ii);
1343 int functions::decodeInteger(const char* data)
1346 char* w((char*) &result);
1348 *(w + 1) = *(data + 1);
1349 *(w + 2) = *(data + 2);
1350 *(w + 3) = *(data + 3);
1351 return ntohl(result);
1354 short int functions::decodeShort(const char* data)
1357 char* w((char*) &result);
1359 *(w + 1) = *(data + 1);
1360 return ntohs(result);
1363 S64 functions::decodeInteger64(const char* data)
1365 S64 result(decodeInteger(data));
1367 return result |= (decodeInteger(data + sizeof(int)) & 0xffffffff);
1371 float functions::decodeFloat(const char* data)
1374 int ii = functions::decodeInteger(data);
1375 anna_memcpy(&result, &ii, sizeof(result));
1380 double functions::decodeDouble(const char* data)
1383 S64 ii = functions::decodeInteger64(data);
1384 anna_memcpy(&result, &ii, sizeof(result));
1390 void functions::decodeIsupNumber(const char *buffer, int length, isup_number_t & isupNumber, bool calledOrCalling) throw(anna::RuntimeException) {
1391 #define DECODE2BYTES_INDX_VALUETYPE(buffer,indx,value_type) ((((value_type)buffer[indx] << 8) & 0xFF00) + ((value_type)buffer[indx+1] & 0x00FF))
1393 isupNumber.OddEven = (short)((buffer[0] >> 7) & 0x01);
1394 bool filler = isupNumber.OddEven;
1396 if(filler && ((buffer [length - 1] & 0xf0) != 0x00))
1397 throw anna::RuntimeException("functions::decodeIsupNumber | Isup number filler must be '0000'", ANNA_FILE_LOCATION);
1399 isupNumber.NatureOfAddress = (short)(buffer[0] & 0x7F);
1400 isupNumber.NumberingPlan = (short)((buffer[1] >> 4) & 0x07);
1402 if(calledOrCalling) {
1403 isupNumber.InternalNetworkNumber = (short)((buffer[1] >> 7) & 0x01);
1405 isupNumber.NumberIncomplete = (short)((buffer[1] >> 7) & 0x01);
1406 isupNumber.AddressPresentationRestricted = (short)((buffer[1] >> 2) & 0x03);
1407 isupNumber.Screening = (short)(buffer[1] & 0x03);
1411 isupNumber.Digits = "";
1414 for(int k = 2; k < length; k ++) {
1415 byte = (buffer [k] & 0x0f);
1416 isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1417 byte = (buffer [k] & 0xf0) >> 4;
1418 isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1421 if(filler) isupNumber.Digits.erase(isupNumber.Digits.size() - 1, 1); // remove filler
1425 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, std::string & target) throw(anna::RuntimeException) {
1427 if(isupNumber.OddEven < 0 || isupNumber.OddEven > 1)
1428 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field out of range [0,1]", ANNA_FILE_LOCATION);
1430 bool odd = isupNumber.OddEven;
1431 bool oddDigits = (isupNumber.Digits.size() % 2);
1433 if(odd != oddDigits)
1434 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field doesn't correspond to the number of digits on 'Digits' field", ANNA_FILE_LOCATION);
1436 if(isupNumber.NatureOfAddress < 0 || isupNumber.NatureOfAddress > 127)
1437 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NatureOfAddress' field out of range [0,127]", ANNA_FILE_LOCATION);
1439 if(isupNumber.NumberingPlan < 0 || isupNumber.NumberingPlan > 7)
1440 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberingPlan' field out of range [0,7]", ANNA_FILE_LOCATION);
1442 if(calledOrCalling) {
1443 if(isupNumber.NumberIncomplete != 0)
1444 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field present on Called Party Number !", ANNA_FILE_LOCATION);
1446 if(isupNumber.AddressPresentationRestricted != 0)
1447 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field present on Called Party Number !", ANNA_FILE_LOCATION);
1449 if(isupNumber.Screening != 0)
1450 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field present on Called Party Number !", ANNA_FILE_LOCATION);
1452 if(isupNumber.InternalNetworkNumber < 0 || isupNumber.InternalNetworkNumber > 1)
1453 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field out of range [0,1]", ANNA_FILE_LOCATION);
1455 if(isupNumber.InternalNetworkNumber != 0)
1456 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field present on Calling Party Number !", ANNA_FILE_LOCATION);
1458 if(isupNumber.NumberIncomplete < 0 || isupNumber.NumberIncomplete > 1)
1459 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field out of range [0,1]", ANNA_FILE_LOCATION);
1461 if(isupNumber.AddressPresentationRestricted < 0 || isupNumber.AddressPresentationRestricted > 3)
1462 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field out of range [0,3]", ANNA_FILE_LOCATION);
1464 if(isupNumber.Screening < 0 || isupNumber.Screening > 3)
1465 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field out of range [0,3]", ANNA_FILE_LOCATION);
1470 bool filler = isupNumber.OddEven;
1471 bool hasDigits = (isupNumber.Digits.size() > 0);
1472 byte = filler ? 0x80 : 0x00;
1473 byte |= isupNumber.NatureOfAddress;
1476 if(calledOrCalling) {
1477 byte = isupNumber.InternalNetworkNumber << 7;
1478 byte |= (isupNumber.NumberingPlan << 4);
1480 byte = isupNumber.NumberIncomplete << 7;
1481 byte |= (isupNumber.NumberingPlan << 4);
1482 byte |= (isupNumber.AddressPresentationRestricted << 2);
1483 byte |= isupNumber.Screening;
1489 std::string dtlc = isupNumber.Digits; // digits to lower case
1490 //std::transform(dtlc.begin(), dtlc.end(), dtlc.begin(), std::tolower);
1491 const char *digits = dtlc.c_str();
1493 for(int k = 1; k < isupNumber.Digits.size(); k += 2) {
1494 if(isxdigit(byte = digits [k - 1]) == 0)
1495 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1497 hex = (byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a);
1499 if(isxdigit(byte = digits [k]) == 0)
1500 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1502 hex |= ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a)) << 4;
1506 if(hasDigits && filler) {
1507 if(isxdigit(byte = digits [isupNumber.Digits.size() - 1]) == 0)
1508 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1510 target += ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a));
1515 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, char * buffer, int & length) throw(anna::RuntimeException) {
1517 codeIsupNumber(isupNumber, calledOrCalling, target);
1518 length = target.size();
1519 memcpy(buffer, target.c_str(), length);