[Simh] Hecnet client...

Jason Stevens neozeed at gmail.com
Tue Feb 17 15:51:22 EST 2009


I made some changes, and slight improvements, and added _WIN32
support... It works right away unlike before needing the bridge to
send a packet before the socket structure was ok for sending.... I
know the global variables I use are weak (and shamelessly taken from a
simple UDP client program) and I don't check for would block errors,
just ignore all socket errors... But it's ok for testing for now.

Right now it only handles numeric addresses...

att xq0 192.168.0.1:7777

Otherwise, thats about it.

The following code can replace the Non Implemented block in
sim_ether.c or you can make your own block etc etc...




struct sockaddr_in si_me, si_other;
int s, i, slen;
char host[55];
char port[16];

#define BUFLEN 1518

#ifdef _WIN32
int inet_aton (const char * str, struct in_addr * add)
{
    add->s_addr = inet_addr( str );
    if( add->s_addr == INADDR_NONE )
        return 0;
    return 1;
}
#endif


t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit)
{
int32 fl;
char parsename[255];
char *pch;
#if defined (_WIN32)
WORD wVersionRequested;
WSADATA wsaData;
#endif

memset(&host,0x0,sizeof(host));
memset(&port,0x0,sizeof(port));
memset(&parsename,0x0,sizeof(parsename));
sprintf(parsename,"%s",name);
pch=strchr(parsename,':');
*pch=' ';
sscanf(parsename,"%s %s",&host,&port);
printf("HECnet connecting to %s:%s\n",host,port);

slen=sizeof(si_other);

#if defined (_WIN32)
wVersionRequested = MAKEWORD (1, 1);
WSAStartup (wVersionRequested, &wsaData);
#endif

if ((s=socket(PF_INET, SOCK_DGRAM, 0))==-1)
        printf("socket error\n");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = PF_INET;
si_me.sin_port = htons(atoi(port));
si_me.sin_addr.s_addr = INADDR_ANY;
if (bind(s, &si_me, sizeof(si_me))==-1)
        {
        printf("error binding socket\n");
        exit(-1);
        }

#if defined (_WIN32)
unsigned long non_block=1;
ioctlsocket(s,FIONBIO,&non_block);
#else
fl = fcntl (s, F_GETFL,0);
fcntl (s, F_SETFL, fl | O_NONBLOCK);
#endif
return SCPE_OK;
}

t_stat eth_close (ETH_DEV* dev)
{
close(s);
return SCPE_OK;
}

t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
{
char buf[BUFLEN];

si_other.sin_family=PF_INET;
si_other.sin_port=htons(atoi(port));
inet_aton(host,&si_other.sin_addr);

slen=sizeof(si_other);

        if (sendto(s, packet->msg, packet->len, 0, &si_other, slen)==-1)
                {  //error sending packet!
                if(routine)
                        (routine)(1);
                }
        else{
                if(routine)
                (routine)(0);}
return SCPE_OK;
}


t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
{
char buf[2500];
int rc;

if(!dev) return SCPE_UNATT;
if(!packet) return SCPE_ARG;

dev->read_packet = packet;
packet->len = 0;
dev->read_callback = routine;

slen=sizeof(si_other);

memset(&buf,0x0,sizeof(buf));
rc=recvfrom(s, buf, BUFLEN, 0, &si_other, &slen);
if (rc==-1)
        {} //error?
else {
        dev->read_packet->len=rc;
       memcpy(dev->read_packet->msg,buf,rc);
       eth_add_crc32(dev->read_packet);
       if(dev->read_callback)
        (dev->read_callback)(0);
}

return SCPE_OK;
}

t_stat eth_filter (ETH_DEV* dev, int addr_count,
                   ETH_MAC* addresses,
                   ETH_BOOL all_multicast,
                   ETH_BOOL promiscuous)
{
return SCPE_OK;
}

int eth_devices (int max, ETH_LIST* dev)
{
return SCPE_OK;
}



More information about the Simh mailing list