Files
fail/debuggers/t32/api/hlinknet.cc
2013-03-05 17:29:48 +01:00

909 lines
23 KiB
C++

/****************************************************************
* *
* Copyright by Lauterbach GmbH *
* Alle Rechte vorbehalten - All rights reserved *
* *
*****************************************************************
Module: hlinknet.c
Function: Low level communication protocol for talking to TRACE32.
Is used by CAPI routined implemented in hremote.c.
Link both files with your application.
***************************************************************/
#include "t32.h"
#if defined(_MSC_VER)
# pragma warning( push )
# pragma warning( disable : 4255 )
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef MS_WINDOWS
# include <winsock2.h>
# include <windows.h>
# include <fcntl.h>
typedef int socklen_t;
#endif
#ifdef DEC_VMS
# include <file.h>
# include <time.h>
# include <errno.h>
# include <socket.h>
# include <inet.h>
# include <netdb.h>
# include <in.h>
# define DONT_USE_ASYNC
# define fd_set int
# define FD_ZERO(fdset) (*fdset = 0)
# define FD_SET(fd,fdset) (*fdset |= (1<<(fd)))
# define FD_ISSET(fd,fdset) (*fdset & (1<<(fd)))
#endif
#ifdef __linux__
# include <fcntl.h>
# include <unistd.h>
# include <sys/time.h>
# include <errno.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
# include <sys/select.h>
#endif
#ifdef UNIX_V
# include <fcntl.h>
# include <unistd.h>
# include <sys/time.h>
# include <errno.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
# if defined(T32HOST_HPUX) || defined(HP_UX)
typedef int socklen_t;
# else
# include <sys/select.h>
# endif
#endif
#ifdef OS_9
# include <fcntl.h>
# include <sys/time.h>
# include <errno.h>
# include <inet/socket.h>
# include <inet/in.h>
# include <inet/netdb.h>
#endif
#if defined(_MSC_VER)
# pragma warning( pop )
#endif
#define PCKLEN_MAX 1472 /* maximum size of UDP-packet */
#define BUFLEN_MIN 6000 /* !!! keep in sync with hassist.c remoteapi !!! */
#ifndef MS_WINDOWS
# ifndef UNIX_V
extern struct hostent * gethostbyaddr();
# endif
#endif
#if defined(DEC_VMS) || defined(MS_WINDOWS) || defined(OS_9) || defined(LINUX)
# define RECEIVEADDR (&ReceiveSocketAddress)
static struct sockaddr ReceiveSocketAddress;
#else
# define RECEIVEADDR 0
#endif
typedef struct LineStruct_s {
char NodeName[80]; /* node name of host running T32 SW */
int CommSocket; /* socket for communication */
unsigned short HostPort; /* Host side port */
unsigned short ReceivePort; /* Receiver Port */
unsigned short TransmitPort; /* Transmitter Port in T32 */
int PacketSize; /* Max. size of UDP-packet data */
int PollTimeSec;
int ReceiveToggleBit;
unsigned char MessageId;
int LineUp;
unsigned short ReceiveSeq, TransmitSeq; /* block-ids */
unsigned short LastReceiveSeq, LastTransmitSeq;
unsigned char* LastTransmitBuffer;
int LastTransmitSize;
struct sockaddr_in SocketAddress;
} LineStruct;
#ifdef MS_WINDOWS
extern void T32_InstallAsyncSelect(HWND hwnd, int msg);
extern void T32_UnInstallAsyncSelect(HWND hwnd);
#endif
extern void LINE_SetReceiveToggleBit(int value);
extern int LINE_GetReceiveToggleBit(void);
extern int LINE_GetNextMessageId(void);
extern int LINE_GetMessageId(void);
extern int LINE_GetLineParamsSize (void);
extern void LINE_SetDefaultLineParams (LineStruct* params);
extern LineStruct* LINE_GetLine0Params (void);
extern void LINE_SetLine (LineStruct* params);
extern int LINE_LineConfig(char * in);
extern void LINE_LineExit(void);
extern int LINE_LineInit(char * message);
extern int LINE_LineTransmit(unsigned char * in, int size);
extern int LINE_LineDriverGetSocket(void);
extern int LINE_LineReceive(unsigned char * out);
extern int LINE_ReceiveNotifyMessage(unsigned char* package);
extern int LINE_LineSync(void);
static int Connection(unsigned char *ipaddrused);
static struct timeval LongTime = { 0, 500000 };
static const LineStruct LineDefaultParams = {
"localhost", -1, 0, 0, 20000, 1024, 5, -1, 0, 0};
static LineStruct Line0Params = {
"localhost", -1, 0, 0, 20000, 1024, 5, -1, 0, 0};
static LineStruct* pLineParams = &Line0Params;
static int str2dec (char* in)
{
int x = 0;
while (*in) {
x *= 10;
if (*in < '0' || *in > '9')
return -1;
x += *in - '0';
in++;
}
return x;
}
void LINE_SetReceiveToggleBit(int value)
{
pLineParams->ReceiveToggleBit = value;
}
int LINE_GetReceiveToggleBit(void)
{
return pLineParams->ReceiveToggleBit;
}
int LINE_GetNextMessageId(void)
{
return ++pLineParams->MessageId;
}
int LINE_GetMessageId(void)
{
return pLineParams->MessageId;
}
int LINE_GetLineParamsSize (void)
{
return sizeof (LineStruct);
}
void LINE_SetDefaultLineParams (LineStruct* params)
{
*params = LineDefaultParams;
return;
}
LineStruct* LINE_GetLine0Params (void)
{
return &Line0Params;
}
void LINE_SetLine (LineStruct* params)
{
pLineParams = params;
}
int LINE_LineConfig(char * in)
{
int x;
LineStruct* line = pLineParams;
if (!strncmp((char *) in, "NODE=", 5)) {
strcpy(line->NodeName, in+5);
return 1;
}
if (!strncmp((char *) in, "PORT=", 5)) {
x = str2dec (in+5);
if (x == -1)
return -1;
line->TransmitPort = x;
return 1;
}
if (!strncmp((char *) in, "HOSTPORT=", 9)) {
x = str2dec (in+9);
if (x == -1)
return -1;
line->HostPort = x;
return 1;
}
if (!strncmp((char *) in, "PACKLEN=", 8)) {
x = str2dec (in+8);
if (x == -1)
return -1;
line->PacketSize = x;
return 1;
}
if (!strncmp((char *) in, "TIMEOUT=", 8)) {
x = str2dec (in+8);
if (x == -1)
return -1;
line->PollTimeSec = x;
return 1;
}
return -1;
}
static void WinsockErrorMessage(char * out)
{
#ifdef MS_WINDOWS
int err;
err = WSAGetLastError();
switch (err) {
case WSAHOST_NOT_FOUND:
strcat(out, " (HOST_NOT_FOUND)");
break;
case WSATRY_AGAIN:
strcat(out, " (TRY_AGAIN)");
break;
case WSANO_RECOVERY:
strcat(out, " (NO_RECOVERY)");
break;
case WSANO_DATA:
strcat(out, " (NO_DATA)");
break;
case WSAEINTR:
strcat(out, " (INTR)");
break;
case WSANOTINITIALISED:
strcat(out, " (NOTINITIALISED)");
break;
case WSAENETDOWN:
strcat(out, " (NETDOWN)");
break;
case WSAEAFNOSUPPORT:
strcat(out, " (WSAEAFNOSUPPORT)");
break;
case WSAEINPROGRESS:
strcat(out, " (INPROGRESS)");
break;
case WSAEMFILE:
strcat(out, " (WSAEMFILE)");
break;
case WSAENOBUFS:
strcat(out, " (WSAENOBUFS)");
break;
case WSAEPROTONOSUPPORT:
strcat(out, " (WSAEPROTONOSUPPORT)");
break;
case WSAEPROTOTYPE:
strcat(out, " (WSAEPROTOTYPE)");
break;
case WSAESOCKTNOSUPPORT:
strcat(out, " (WSAESOCKTNOSUPPORT)");
break;
}
#endif
}
static long GetInetAddress(char * name, char * message)
{
struct hostent *hp;
int i1, i2, i3, i4;
char ownname[256];
if (name == NULL) {
gethostname(ownname, sizeof(ownname));
name = ownname;
}
i1 = i2 = i3 = i4 = 0;
if (sscanf(name, "%d.%d.%d.%d", &i1, &i2, &i3, &i4) == 4) {
if (i1 || i2 || i3 || i4) {
return (i1 << 24) | (i2 << 16) | (i3 << 8) | (i4);
}
}
hp = gethostbyname(name);
if (!hp) {
strcpy(message, "node name (");
strcat(message, name);
strcat(message, ") unknown");
WinsockErrorMessage(message);
return -1l;
}
return ntohl(*(long *) (hp->h_addr));
}
void LINE_LineExit(void)
{
int i;
LineStruct* line = pLineParams;
static const unsigned char discon[] = {4, 0, 0, 0, 0, 0, 0, 0, 'T', 'R', 'A', 'C', 'E', '3', '2', 0};
if (!line->LineUp)
return;
if (line->CommSocket != -1) {
for (i = 0; i < 5; i++)
sendto(line->CommSocket, (char *) discon, 16, 0, (struct sockaddr *) &(line->SocketAddress), sizeof(line->SocketAddress)); /* send EXIT 4 */
#ifdef MS_WINDOWS
closesocket(line->CommSocket);
#endif
#if defined(DEC_VMS) || defined(UNIX_V) || defined(OS_9)
close(line->CommSocket);
#endif
}
#ifdef MS_WINDOWS
WSACleanup();
#endif
line->CommSocket = -1;
line->LineUp = 0;
}
int LINE_LineInit(char * message)
{
int i, j;
socklen_t length;
int val;
unsigned char ipaddrused[4];
long remote_ip;
int buflen;
LineStruct* line = pLineParams;
if (line->LineUp)
return 0;
if (line->CommSocket == -1) {
#ifdef MS_WINDOWS
WSADATA wsaData;
if (WSAStartup(0x0101, &wsaData)) {
strcpy(message, "TCP/IP not ready, check configuration");
return -1;
}
#endif
}
if ((remote_ip = GetInetAddress(line->NodeName, message)) == -1l)
return -1;
if (line->CommSocket == -1) {
line->SocketAddress.sin_family = AF_INET;
line->SocketAddress.sin_addr.s_addr = INADDR_ANY;
line->SocketAddress.sin_port = line->HostPort; /* Port can be determined by
* host */
if ((line->CommSocket = (int)socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
strcpy(message, "cannot create socket");
WinsockErrorMessage(message);
goto done;
}
if ((i = bind(line->CommSocket, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress))) == -1) {
strcpy(message, "cannot bind socket");
WinsockErrorMessage(message);
goto done;
}
length = sizeof(line->SocketAddress);
if (getsockname(line->CommSocket, (struct sockaddr *) & line->SocketAddress, &length) == -1) {
strcpy(message, "cannot identify port");
WinsockErrorMessage(message);
goto done;
}
line->ReceivePort = ntohs(line->SocketAddress.sin_port);
line->SocketAddress.sin_family = AF_INET;
line->SocketAddress.sin_addr.s_addr = INADDR_ANY;
line->SocketAddress.sin_port = htons(line->TransmitPort);
}
line->SocketAddress.sin_addr.s_addr = htonl(remote_ip);
buflen = 18000;
#if !defined(OS_9)
val = 0;
length = sizeof(val);
getsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, &length);
if (val > 0 && val < line->PacketSize)
line->PacketSize = val;
if (val < buflen) {
val = buflen;
length = sizeof(val);
if (setsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, length) == -1) {
strcpy(message, "cannot alloc buffer for rcvsocket");
goto done;
}
val = 0;
length = sizeof(val);
getsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, &length);
if (val < buflen) {
strcpy(message, "cannot alloc buffer for rcvsocket");
goto done;
}
}
val = 0;
length = sizeof(val);
getsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, &length);
if (val < buflen) {
val = buflen;
length = sizeof(val);
if (setsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, length) == -1) {
strcpy(message, "cannot alloc buffer for sndsocket");
goto done;
}
val = 0;
length = sizeof(val);
getsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, &length);
if (val < buflen) {
strcpy(message, "cannot alloc buffer for sndsocket");
goto done;
}
}
#endif
for (i = 0; i < 10; i++) {
j = Connection(ipaddrused);
if (j == 0)
continue;
if (j == 1) {
line->LineUp = 1;
return 1;
}
strcpy(message, "TRACE32 access refused");
goto done;
}
strcpy(message, "TRACE32 not responding");
done:
LINE_LineExit(); /* Close connection if no success */
return -1;
}
#ifdef MS_WINDOWS
void T32_InstallAsyncSelect(HWND hwnd, int msg)
{
#ifndef DONT_USE_ASYNC
WSAAsyncSelect(pLineParams->CommSocket, hwnd, msg, FD_READ);
#endif
}
void T32_UnInstallAsyncSelect(HWND hwnd)
{
#ifndef DONT_USE_ASYNC
WSAAsyncSelect(pLineParams->CommSocket, hwnd, 0, 0);
#endif
}
#endif
/**
Sends a message to T32. Handles segmentation of _message_ into (one
or multiple) _packages_.
@param in pointer to outgoing message (already includes 5 byte message header)
@param size size of message
@note the message must be allocated such that there is space in
front of the message for adding the packet header
*/
int LINE_LineTransmit(unsigned char * in, int size)
{
int packetSize;
unsigned int tmpl;
int result;
unsigned int bytesTransmitted = 0;
LineStruct* line = pLineParams;
unsigned char receivebuffer[HANDSHAKE_RECEIVEBUFFERSIZE];
line->LastTransmitBuffer = in;
line->LastTransmitSize = size;
line->LastTransmitSeq = line->TransmitSeq;
in -= 4; /* space for packet header */
/* Assumed that Host SocketReceivebuffersize is 6000 (see hassist.c) */
do {
packetSize = (size > line->PacketSize - 4) ? line->PacketSize - 4 : size;
/* When sending multiple packets, the packet header is written inside the
message's payload. Original contents needs to be saved/restored */
SETLONGVAR(tmpl, in[0]); /* save */
in[0] = 0x11; /* transmit data package */
in[1] = (size > packetSize) ? 1 : 0; /* more packets follow */
SETWORDVAR(in[2], line->TransmitSeq); /* packet sequence ID */
if (sendto( line->CommSocket, (char *) in, packetSize + 4, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress) ) != packetSize + 4) { /* send Data Package 0x11 */
SETLONGVAR(in[0], tmpl); /* restore buffer */
return 0;
}
bytesTransmitted += packetSize + 4;
if( (bytesTransmitted + line->PacketSize) > BUFLEN_MIN ) {
socklen_t length;
length=sizeof(struct sockaddr);
if( (result = recvfrom(line->CommSocket, (char *)receivebuffer, 1, 0, (struct sockaddr *) RECEIVEADDR, &length)) < 0) {
return -1;
}
}
SETLONGVAR(in[0], tmpl); /* restore buffer */
line->TransmitSeq++;
in += packetSize;
size -= packetSize;
}
while (size > 0); /* more packets required? */
return line->LastTransmitSize;
}
/** Receives a package from the socket, with timeout handling.
@return number of received bytes or error number (<0)
*/
static int ReceiveWithTimeout(struct timeval *tim, unsigned char *dest, int size)
{
int i;
fd_set readfds;
socklen_t length;
struct timeval timeout;
LineStruct* line = pLineParams;
timeout = *tim;
#ifdef POLL_NET
DWORD endpoll;
static struct timeval tival = {0};
if (tim->tv_usec || tim->tv_sec)
endpoll = GetCurrentTime() + tim->tv_usec / 1000 + tim->tv_sec * 1000;
else
endpoll = 0;
retry:
#endif
FD_ZERO(&readfds);
FD_SET( (unsigned int)line->CommSocket, &readfds);
#ifdef POLL_NET
i = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tival);
if (i < 0)
return i;
if (i == 0) {
if (endpoll) {
if (GetCurrentTime() < endpoll) {
ScreenDispatcher();
goto retry;
}
}
return i;
}
#else
i = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &timeout);
#endif
if (i <= 0) {
return i;
}
length = sizeof(struct sockaddr);
return recvfrom(line->CommSocket, (char *)dest, size, 0, (struct sockaddr *) RECEIVEADDR, &length);
}
int LINE_LineDriverGetSocket(void)
{
return pLineParams->CommSocket;
}
/* Queue pending notifications */
T32_NotificationPackage *T32_NotificationHead = NULL, *T32_NotificationTail = NULL;
/** Receives messages from the socket. Assembles multiple packets into
a single message.
@param out output buffer for storing payload. Attention: there must
be some space _before_ the output buffer (4 bytes or more)
for temporary usage.
@return number of bytes of the message or error number (<0)
*/
int LINE_LineReceive(unsigned char * out)
{
int i, flag;
int count;
unsigned short tmpw;
unsigned int tmpl;
unsigned short s;
LineStruct* line = pLineParams;
register unsigned char *dest;
static unsigned char handshake[] = {7, 0, 0, 0, 0, 0, 0, 0, 'T', 'R', 'A', 'C', 'E', '3', '2', 0};
retry:
dest = out-4; /* adjust pointer so we place header BEFORE "out" and thus payload AT "out" */
count = 0;
s = line->ReceiveSeq;
do {
/* multiple packets are merged in-place: backup data that is
overwritten package aby header */
SETLONGVAR(tmpl, dest[0]);
do {
struct timeval PollTime = {0, 0};
PollTime.tv_sec = line->PollTimeSec;
if ((i = ReceiveWithTimeout(&PollTime, dest, line->PacketSize)) <= 0) {
if (i == -2)
goto retry;
return -1;
}
/* we got a handshakepackage */
if( (i == 1) && (dest[0] == '+') )
{
goto retry;
}
if (i <= 4) {
return -1;
}
/* Detect and enqeue async notification that slipped into a request/reply pair */
if (dest[0] == T32_API_NOTIFICATION)
{
T32_NotificationPackage *newPackage, *oldHead;
newPackage = (T32_NotificationPackage *)malloc(sizeof(T32_NotificationPackage));
if (newPackage==NULL)
return -1;
memcpy(newPackage, dest, i); /* in theory i should always be the package size, at least for ethernet */
oldHead = T32_NotificationHead;
newPackage->prev = NULL;
newPackage->next = oldHead;
if (oldHead)
oldHead->prev = newPackage;
T32_NotificationHead = newPackage;
if (T32_NotificationTail==NULL) {
T32_NotificationTail=newPackage;
}
goto retry;
}
if (dest[0] != T32_API_RECEIVE) {
return -1;
}
SETWORDVAR(tmpw, dest[2]);
if (tmpw == line->LastReceiveSeq && line->LastTransmitSize) {
line->TransmitSeq = line->LastTransmitSeq;
LINE_LineTransmit(line->LastTransmitBuffer, line->LastTransmitSize);
}
}
while (tmpw != line->ReceiveSeq);
line->ReceiveSeq++;
flag = dest[1];
SETLONGVAR(dest[0], tmpl); /* restore payload overwritten by package header */
dest += i - 4;
count += i - 4;
if (count > LINE_MSIZE) {
return -1;
}
if (flag == 2) {
if (sendto(line->CommSocket, (char *) handshake, 16, 0, (struct sockaddr *) &line->SocketAddress, sizeof(line->SocketAddress)) != 16) { /* send Handshake 7 */
return -1;
}
}
}
while (flag);
line->LastReceiveSeq = s;
return count;
}
/** Receives notification messages. First checks for a queued
notification and if none is available polls the socket for new
notifications. For getting all pending notifications call the
function until it returns -1.
@param package output buffer of size T32_PCKLEN_MAX for the package
@return -1 no notification pending,
>=0 notificataion type T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG
*/
int LINE_ReceiveNotifyMessage(unsigned char* package)
{
int len;
static struct timeval LongTime = {0, 0};
/* Check for asynchronous notifications */
if (T32_NotificationTail) {
T32_NotificationPackage *prev = T32_NotificationTail->prev;
if (prev)
prev->next = NULL;
memcpy(package, T32_NotificationTail->payload, T32_PCKLEN_MAX);
free(T32_NotificationTail);
T32_NotificationTail = prev;
if (prev==NULL) /* deleted last message */
T32_NotificationHead = NULL;
} else {
len = ReceiveWithTimeout(&LongTime, package, T32_PCKLEN_MAX);
if (len < 2)
return -1;
}
if (package[0] != T32_API_NOTIFICATION)
return -1;
return package[1]; /* type of notification: T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG */
}
/** Sends sync packets */
int LINE_LineSync(void)
{
int i, j;
unsigned char packet[T32_PCKLEN_MAX];
static char magicPattern[] = "TRACE32";
LineStruct* line = pLineParams;
j = 0;
memset(packet, 0, sizeof(packet));
retry:
packet[0] = T32_API_SYNCREQUEST;
packet[1] = 0;
SETWORDVAR(packet[2], line->TransmitSeq);
SETWORDCONST(packet[4], 0);
SETWORDCONST(packet[6], 0);
strcpy((char *) (packet + 8), magicPattern);
if (sendto(line->CommSocket, (char *) packet, 16 /*size*/, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) { /* Send SyncReq 2 */
return -1;
}
while (1) { /* empty queue */
if (++j > 20) {
return -1;
}
if ((i = ReceiveWithTimeout(&LongTime, packet, T32_PCKLEN_MAX)) <= 0) {
return -1;
}
if (i != 16 || packet[0] != T32_API_SYNCACKN || strcmp((char *) packet + 8, magicPattern)) {
if (i == 16 && packet[0] == 5)
goto retry;
continue;
}
break;
}
SETWORDVAR(line->ReceiveSeq, packet[2]);
line->LastReceiveSeq = line->ReceiveSeq - 100;
packet[0] = T32_API_SYNCBACK;
packet[1] = 0;
SETWORDVAR(packet[2], line->TransmitSeq);
SETWORDCONST(packet[4], 0);
SETWORDCONST(packet[6], 0);
strcpy((char *) (packet + 8), magicPattern);
if (sendto(line->CommSocket, (char *) packet, 16, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) { /* Send SyncBack 0x22 */
return -1;
}
return 1;
}
static int Connection(unsigned char *ipaddrused)
{
int i;
unsigned char buffer[T32_PCKLEN_MAX];
LineStruct* line = pLineParams;
static const char magicPattern[] = "TRACE32";
memset(buffer, 0, sizeof(buffer));
buffer[0] = 3; /* CONNECTREQUEST */
buffer[1] = 0;
line->TransmitSeq = 1;
SETWORDVAR(buffer[2], line->TransmitSeq);
SETWORDVAR(buffer[4], line->TransmitPort);
SETWORDVAR(buffer[6], line->ReceivePort);
strcpy((char *) (buffer + 8), magicPattern);
if (sendto(line->CommSocket, (char *) buffer, line->PacketSize, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) { /* send ConnectReq 3 */
return 0;
}
if ((i = ReceiveWithTimeout(&LongTime, buffer, line->PacketSize)) <= 0) {
return 0;
}
if (strcmp((char *) (buffer + 8), magicPattern)) {
return 0;
}
SETWORDVAR(line->ReceiveSeq, buffer[2]);
if (buffer[0] == 0x53) { /* POSITIVE CONNECTACKN from Debug Unit ? */
ipaddrused[0] = 1;
ipaddrused[1] = 1;
ipaddrused[2] = 1;
ipaddrused[3] = 11;
return 2;
}
if (buffer[0] != 0x13) { /* POSITIVE CONNECTACKN ? */
if (buffer[0] == 0x23) {/* NEGATIVE ? */
ipaddrused[0] = buffer[4];
ipaddrused[1] = buffer[5];
ipaddrused[2] = buffer[6];
ipaddrused[3] = buffer[7];
return 2;
}
return 0;
}
line->PacketSize = i;
return 1;
}
/* .NET helpers: additional functions to interface managed and unmanaged memory */
#ifdef __cplusplus
extern "C" void *LINE_AllocNewChannel()
{
return malloc(sizeof(LineStruct));
}
extern "C" void LINE_FreeAllocChannel(void * p)
{
free(p);
}
#endif