From OpenTTCN
#include "Utilities.h"
#include <isl/TTCN3.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
#include <malloc.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
typedef int socklen_t;
#endif
#define MAX_BUFFER_SIZE 8192
int _socketDesc = 0;
int _socketDescInitialized = 0;
long tciValueToLong(TciValue value)
{
String valNumberAbs;
Boolean valNumberSign;
char* valNumber;
long val;
valNumberAbs = tciGetIntAbs(value);
valNumberSign = tciGetIntSign(value);
valNumber = (char *) malloc(strlen(valNumberAbs) + 2);
valNumber[0] = valNumberSign ? '+' : '-';
strcpy(valNumber + 1, valNumberAbs);
val = atol(valNumber);
free(valNumber);
return val;
}
void assignLongToTciValue(TciValue dst, long value)
{
char valAbsValue[MAX_BUFFER_SIZE];
Boolean valSignValue;
valSignValue = (value >= 0) ? 1 : 0;
if (value < 0) value = -value;
sprintf(valAbsValue, "%li", value);
tciSetIntAbs(dst, valAbsValue);
tciSetIntSign(dst, valSignValue);
}
TciValue longToTciValue(long value)
{
TciValue result = tciNewInstance(tciGetIntegerType());
assignLongToTciValue(result, value);
return result;
}
void tciValueToCharstring(char** dst_str, long* dst_str_len, TciValue value)
{
long len = 0;
TciCharStringValue cStringValue = tciGetCStringValue(value);
len = (long) cStringValue.length;
*dst_str = (char *) malloc(len + 1);
*dst_str_len = len;
memcpy(*dst_str, cStringValue.string + 1, len);
(*dst_str)[len] = 0;
}
void assignCharstringToTciValue(TciValue dst, const char* value)
{
TciCharStringValue cStringValue;
int len = (int) strlen(value);
char* rawValue = (char *) malloc(len + 3);
sprintf(rawValue, "\"%s\"", value);
cStringValue.length = len;
cStringValue.string = rawValue;
tciSetCStringValue(dst, cStringValue);
free(rawValue);
}
TciValue charstringToTciValue(const char* value)
{
TciValue result = tciNewInstance(tciGetTciCharstringType());
assignCharstringToTciValue(result, value);
return result;
}
void assignSizedCharstringToTciValue(TciValue dst, const char* value, long len)
{
TciCharStringValue cStringValue;
char* rawValue = (char *) malloc(len + 3);
rawValue[0] = '"';
memcpy(rawValue + 1, value, len);
rawValue[len + 1] = '"';
rawValue[len + 2] = 0;
cStringValue.length = len;
cStringValue.string = rawValue;
tciSetCStringValue(dst, cStringValue);
free(rawValue);
}
TciValue sizedCharstringToTciValue(const char* value, long len)
{
TciValue result = tciNewInstance(tciGetTciCharstringType());
assignSizedCharstringToTciValue(result, value, len);
return result;
}
int extractHostAndPortFromAddress(
unsigned long* dstIpAddr_,
unsigned short* dstPortNumber_,
TciValue src_)
{
char* str = 0;
long str_len = 0;
unsigned long ipAddr = 0;
TciValue portNumberField = 0;
long port = 0;
/* Extract IP address */
TciValue hostField = tciGetRecFieldValue(src_, "host");
if (!hostField)
{
otReportError("extractHostAndPortFromAddress(): "
"Cannot retrieve address host field.");
return 1;
}
tciValueToCharstring(&str, &str_len, hostField);
ipAddr = inet_addr(str);
free(str);
if (ipAddr == INADDR_NONE)
{
otReportError("extractHostAndPortFromAddress(): Cannot resolve "
"effective IP address extracted from the address host field.");
return 1;
}
/* Extract port */
portNumberField = tciGetRecFieldValue(src_, "portField");
if (!portNumberField)
{
otReportError("extractHostAndPortFromAddress(): "
"Cannot retrieve address portField field.");
return 1;
}
port = tciValueToLong(portNumberField);
/* Assign to the result variables */
*dstIpAddr_ = ipAddr;
*dstPortNumber_ = htons((unsigned short) port);
return 0;
}
/* Returns 0 on success, non-zero on error. */
int bindSocketToAnyPort(int* dstSocketDesc)
{
int rval = 0;
int errorCode = 0;
static struct sockaddr_in myaddr;
*dstSocketDesc = (int) socket(PF_INET, SOCK_DGRAM, 0);
memset (&myaddr, 0, sizeof myaddr);
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
#ifdef _WIN32
myaddr.sin_family = AF_INET;
#endif
myaddr.sin_port = htons(0); /* pick any available port */
rval = bind(*dstSocketDesc, (struct sockaddr *) &myaddr, sizeof myaddr);
if (rval < 0)
{
#ifndef _WIN32
printf("bindSocketToAnyPort(): "
"Error: bind() returned: %s\n", strerror(errno));
#else
int errorCode = WSAGetLastError();
printf("bindSocketToAnyPort(): "
"Error: bind() returned error code %i\n", errorCode);
#endif
return 1;
}
return 0;
}
int sendDatagramPacket(unsigned long host_,
unsigned short port_, const char* data_, long length_)
{
int rval = 0;
int errorCode = 0;
struct sockaddr_in saddr;
memset (&saddr, 0, sizeof saddr);
if (!_socketDescInitialized)
{
rval = bindSocketToAnyPort(&_socketDesc);
if (rval)
{
otReportError("sendDatagramPacket(): Cannot bind socket.");
return 1;
}
_socketDescInitialized = 1;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = host_;
saddr.sin_port = port_;
while (1)
{
rval = sendto(
_socketDesc,
data_,
length_,
0,
(struct sockaddr *) &saddr,
sizeof saddr);
if ((-1 == rval) && ((errno == EAGAIN) || (errno == EINTR)))
{
/* resending */
}
else if (-1 == rval)
{
otReportError("sendDatagramPacket(): Cannot send frame.");
#ifndef _WIN32
printf("sendDatagramPacket(): send error = %s\n", strerror(errno));
#else
errorCode = WSAGetLastError();
printf("sendDatagramPacket(): send error code = %i\n", errorCode);
#endif
return 1;
}
else
{
/* send operation succeeded */
break;
}
}
return 0;
}