dxx-rebirth/arch/win32/arch_ip.cpp
2006-03-20 16:43:15 +00:00

182 lines
4.2 KiB
C++
Executable file

/*
* arch_ip.cpp - arch specific udp/ip code. (win32 ver)
* added 2000/02/07 Matt Mueller (some code borrowed from ipx_udp.c)
*/
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
extern "C" {
#include "ipx_drv.h"
#include "types.h"
#include "mono.h"
//#include "multi.h"
}
#include "ip_base.h"
#include "ipclient.h"
//static int dynamic_socket=0x402;
static int mysock=-1;
//static unsigned char qhbuf[6];
/* Do hostname resolve on name "buf" and return the address in buffer "qhbuf".
*/
int arch_ip_queryhost(ip_addr *addr,char *buf,u_short baseport)
{
struct hostent *he;
char *s;
char c=0;
u_short p;
if ((s=strrchr(buf,':'))) {
c=*s;
*s='\0';
p=ip_portshift(baseport,s+1);
}
else p=ip_portshift(baseport,NULL);//memset(qhbuf+4,0,2);
he=gethostbyname((char *)buf);
if (s) *s=c;
if (!he) {
msg("Error resolving my hostname \"%s\"",buf);
return -1; //(NULL);
}
if (he->h_addrtype!=AF_INET || he->h_length!=4) {
msg("Error parsing resolved my hostname \"%s\"",buf);
return -1;//(NULL);
}
if (!*he->h_addr_list) {
msg("My resolved hostname \"%s\" address list empty",buf);
return -1;//(NULL);
}
addr->set(4,(u_char*)*he->h_addr_list,p);
// memcpy(qhbuf,(*he->h_addr_list),4);
// return(qhbuf);
return 0;
}
#ifdef UDPDEBUG
/* Like dumpraddr() but for structure "sockaddr_in"
*/
static void dumpaddr(struct sockaddr_in *sin)
{
unsigned short ports;
u_char qhbuf[6];
memcpy(qhbuf+0,&sin->sin_addr,4);
//ports=htons(((short)ntohs(sin->sin_port))-UDP_BASEPORT);
ports=sin->sin_port;
memcpy(qhbuf+4,&ports,2);
dumpraddr(qhbuf);
}
#endif
int ip_sendtoca(ip_addr addr,const void *buf,int len){
struct sockaddr_in toaddr;
if (addr.addrlen()!=4) return 0;//not handled yet
toaddr.sin_family=AF_INET;
memcpy(&toaddr.sin_addr,addr.addr,4);
toaddr.sin_port=*(unsigned short *)(addr.addr+4);
#ifdef UDPDEBUG
printf(MSGHDR "sendtoca((%d) ",len);
//dumpraddr(addr.addr);
addr.dump();
puts(").");
#endif
return sendto(mysock,(char*)buf,len,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
}
int arch_ip_get_my_addr(u_short myport){
char buf[256];
if (gethostname(buf,sizeof(buf))) FAIL("Error getting my hostname");
ip_addr ip;
if (ip.dns(buf,myport)) FAIL("Error querying my own hostname \"%s\"",buf);
ip_my_addrs.add(ip);
return 0;
}
int arch_ip_open_socket(int port){
struct sockaddr_in sin;
int val_one=1;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup( wVersionRequested, &wsaData))
{
return -1;
}
#if 0
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 ) {
/* We couldn't find a usable WinSock DLL. */
WSACleanup( );
return -2;
}
#endif
if ((mysock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
mysock = -1;
FAIL("socket() creation failed on port %d: %m",port);
}
if (setsockopt(mysock,SOL_SOCKET,SO_BROADCAST,(char*)&val_one,sizeof(val_one))) {
if (close(mysock)) msg("close() failed during error recovery: %m");
mysock=-1;
FAIL("setsockopt(SO_BROADCAST) failed: %m");
}
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=htonl(INADDR_ANY);
sin.sin_port=htons(port);
if (bind(mysock,(struct sockaddr *)&sin,sizeof(sin))) {
if (close(mysock)) msg("close() failed during error recovery: %m");
mysock=-1;
FAIL("bind() to UDP port %d failed: %m",port);
}
return 0;
}
void arch_ip_close_socket(void) {
if (mysock<0) {
msg("close w/o open");
return;
}
if (closesocket(mysock))
msg("close() failed on CloseSocket D1X ip socket %m");
mysock=-1;
WSACleanup();
}
int arch_ip_recvfrom(char*outbuf,int outbufsize,struct ipx_recv_data *rd){
struct sockaddr_in fromaddr;
int fromaddrsize=sizeof(fromaddr);
int size;
static ip_addr ip_fromaddr;
ip_addr *vptr=&ip_fromaddr;
if ((size=recvfrom(mysock,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0)
return -1;
if (fromaddr.sin_family!=AF_INET) return -1;
#ifdef UDPDEBUG
printf(MSGHDR "recvfrom((%d-2=%d),",size,size-2);
dumpaddr(&fromaddr);
puts(").");
#endif
ip_fromaddr.set(4,(u_char*)&fromaddr.sin_addr,fromaddr.sin_port);
memcpy(rd->src_node,&vptr,sizeof(ip_addr*));
return size;
}
int arch_ip_PacketReady(void) {
return ipx_general_PacketReady(mysock);
}