浏览代码

Added IPV6 support.

woollybah 8 年之前
父节点
当前提交
21f839de61
共有 2 个文件被更改,包括 275 次插入37 次删除
  1. 91 4
      stdc.mod/stdc.bmx
  2. 184 33
      stdc.mod/stdc.c

+ 91 - 4
stdc.mod/stdc.bmx

@@ -42,6 +42,73 @@ ModuleInfo "CC_OPTS: -D_FILE_OFFSET_BITS=64"
 
 Import "stdc.c"
 
+
+Type TAddrInfo
+
+	Field infoPtr:Byte Ptr
+	Field owner:Int
+
+	Method New(infoPtr:Byte Ptr, owner:Int)
+		Self.infoPtr = infoPtr
+		Self.owner = owner
+	End Method
+	
+	Function _Create:TAddrInfo(infoPtr:Byte Ptr, owner:Int) { nomangle }
+		Return New TAddrInfo(infoPtr, owner)
+	End Function
+
+	Function _CreateArray:TAddrInfo[](length:Int) { nomangle }
+		Return New TAddrInfo[length]
+	End Function
+	
+	Function _SetAtIndex(arr:TAddrInfo[], info:TAddrInfo, index:Int) { nomangle }
+		arr[index] = info
+	End Function
+	
+	Method flags:Int()
+		Return bmx_stdc_addrinfo_flags(infoPtr)
+	End Method
+	
+	Method family:Int()
+		Return bmx_stdc_addrinfo_family(infoPtr)
+	End Method
+	
+	Method sockType:Int()
+		Return bmx_stdc_addrinfo_socktype(infoPtr)
+	End Method
+	
+	Method protocol:Int()
+		Return bmx_stdc_addrinfo_protocol(infoPtr)
+	End Method
+	
+	Method addrLen:Int()
+		Return bmx_stdc_addrinfo_addrlen(infoPtr)
+	End Method
+	
+	Method addr:Byte Ptr()
+		Return bmx_stdc_addrinfo_addr(infoPtr)
+	End Method
+	
+	Method canonName:String()
+		Return bmx_stdc_addrinfo_canonname(infoPtr)
+	End Method
+	
+	Method HostName:String()
+		Return bmx_stdc_addrinfo_hostname(infoPtr, 0)
+	End Method
+	
+	Method HostIp:String()
+		Return bmx_stdc_addrinfo_hostname(infoPtr, NI_NUMERICHOST)
+	End Method
+	
+	Method Delete()
+		If owner Then
+			freeaddrinfo(infoPtr)
+		End If
+	End Method
+	
+End Type
+
 'c lib
 Extern "c"
 
@@ -124,7 +191,8 @@ Function atan_!( n! )="atan"
 Const AF_INET_:Int=2					'address types
 Const SOCK_STREAM_:Int=1,SOCK_DGRAM_:Int=2	'communication types
 Const SOCKET_ERROR_:Int=-1
-Const AF_INET6_:Int=30 ' IPv6
+Const AF_INET6_:Int=10 ' IPv6
+Const AF_UNSPEC_:Int = 0
 
 Const SO_DEBUG:Int=1			'turn on debugging info recording 
 Const SO_ACCEPTCONN:Int=2		'socket has had listen() 
@@ -163,6 +231,13 @@ Const TCP_BSDURGENT:Int=$7000
 Const IPPROTO_UDP:Int=17
 Const IPPROTO_TCP:Int=6
 
+Const NI_DGRAM:Int = $0001
+Const NI_NAMEREQD:Int = $0002
+Const NI_NOFQDN:Int = $0004
+Const NI_NUMERICHOST:Int = $0008
+Const NI_NUMERICSERV:Int = $0010
+
+
 'how params for shutdown_
 
 Const SD_SEND:Int=1
@@ -178,14 +253,15 @@ Function closesocket_( socket:Int )
 Function bind_:Int( socket:Int,addr_type:Int,port:Int )
 Function gethostbyaddr_:Byte Ptr( addr:Byte Ptr,addr_len:Int,addr_type:Int )
 
-Function gethostbyname_:Byte Ptr Ptr( name$,addr_type:Int Var,addr_len:Int Var )
+'Function gethostbyname_:Byte Ptr Ptr( name$,addr_type:Int Var,addr_len:Int Var )
+Function getaddrinfo_:TAddrInfo[](name:String, service:String = "http", family:Int = AF_UNSPEC_)
 
-Function connect_:Int( socket:Int,addr:Byte Ptr,addr_type:Int,addr_len:Int,port:Int )
+Function connect_:Int( socket:Int, addrinfo:Byte Ptr )
 Function listen_:Int( socket:Int,backlog:Int )
 Function accept_:Int( socket:Int,addr:Byte Ptr,addr_len:Byte Ptr)
 Function select_:Int( n_read:Int,read_socks:Int Ptr,n_write:Int,write_socks:Int Ptr,n_except:Int,except_socks:Int Ptr,millis:Int )
 Function send_:Size_T( socket:Int,buf:Byte Ptr,size:Size_T,flags:Int )
-Function sendto_:Int( socket:Int,buf:Byte Ptr,size:Int,flags:Int,dest_ip:Byte Ptr,dest_port:Int )
+Function sendto_:Int( socket:Int,buf:Byte Ptr,size:Int,flags:Int,dest_ip:Byte Ptr,dest_port:Int, addr_type:Int = AF_INET_ )
 Function recv_:Size_T( socket:Int,buf:Byte Ptr,size:Size_T,flags:Int )
 Function recvfrom_:Int( socket:Int,buf:Byte Ptr,size:Int,flags:Int,sender_ip:Int Var,sender_port:Int Var)
 Function setsockopt_:Int( socket:Int,level:Int,optname:Int,optval:Byte Ptr,count:Int)
@@ -194,6 +270,17 @@ Function shutdown_:Int( socket:Int,how:Int )
 Function getsockname_:Int( socket:Int,addr:Byte Ptr,addr_len:Int Var )
 Function getpeername_:Int( socket:Int,addr:Byte Ptr,addr_len:Int Var )
 
+Function freeaddrinfo(res:Byte Ptr)
+Function bmx_stdc_addrinfo_flags:Int(info:Byte Ptr)
+Function bmx_stdc_addrinfo_family:Int(info:Byte Ptr)
+Function bmx_stdc_addrinfo_socktype:Int(info:Byte Ptr)
+Function bmx_stdc_addrinfo_protocol:Int(info:Byte Ptr)
+Function bmx_stdc_addrinfo_addrlen:Int(info:Byte Ptr)
+Function bmx_stdc_addrinfo_addr:Byte Ptr(info:Byte Ptr)
+Function bmx_stdc_addrinfo_hostname:String(info:Byte Ptr, flags:Int)
+Function bmx_stdc_addrinfo_canonname:String(info:Byte Ptr)
+Function inet_pton_:Int(family:Int, src:String, dst:Byte Ptr)
+
 'time
 
 Function time_:Int( time:Byte Ptr )

+ 184 - 33
stdc.mod/stdc.c

@@ -33,6 +33,11 @@ FILE* stdin_;
 FILE* stdout_;
 FILE* stderr_;
 
+extern BBObject * pub_stdc_TAddrInfo__Create(struct addrinfo * info, int owner);
+extern BBArray * pub_stdc_TAddrInfo__CreateArray(int count);
+extern void pub_stdc_TAddrInfo__SetAtIndex(BBArray * arr, BBObject * info, int index);
+
+
 #if _WIN32
 
 int getchar_(){
@@ -339,46 +344,104 @@ void closesocket_( int s ){
 #endif
 }
 
+int bmx_stdc_convertAFFamily(int family) {
+	switch (family) {
+		case 2:
+			return AF_INET;
+		case 10:
+			return AF_INET6;
+	}
+	
+	// unmapped
+	return family;
+}
+
+
 int bind_( int socket,int addr_type,int port ){
 	int r;
-	struct sockaddr_in sa;
 	
-	if( addr_type!=AF_INET ) return -1;
-
-	memset( &sa,0,sizeof(sa) );
-	sa.sin_family=addr_type;
-	sa.sin_addr.s_addr=htonl(INADDR_ANY);
-	sa.sin_port=htons( port );
+	//	if ( addr_type!=AF_INET ) return -1;
+
+	switch(addr_type) {
+		case AF_INET:
+		{
+			struct sockaddr_in sa;
+			memset( &sa,0,sizeof(sa) );
+			sa.sin_family= bmx_stdc_convertAFFamily(addr_type);
+			sa.sin_addr.s_addr=htonl(INADDR_ANY);
+			sa.sin_port=htons( port );
+			return bind( socket,(void*)&sa,sizeof(sa) );
+		}
+		case AF_INET6:
+		{
+			struct sockaddr_in6 sa;
+			memset( &sa,0,sizeof(sa) );
+			sa.sin6_family= bmx_stdc_convertAFFamily(addr_type);
+			sa.sin6_addr=in6addr_any;
+			sa.sin6_port=htons( port );
+			return bind( socket,(void*)&sa,sizeof(sa) );
+		}
+		default:
+			return -1;
+	}
 	
-	return bind( socket,(void*)&sa,sizeof(sa) );
 }
 
 char *gethostbyaddr_( void *addr,int addr_len,int addr_type ){
-	struct hostent *e=gethostbyaddr( addr,addr_len,addr_type );
-	return e ? e->h_name : 0;
+	
+	//struct hostent *e=gethostbyaddr( addr,addr_len,addr_type );
+	//return e ? e->h_name : 0;
 }
 
-char **gethostbyname_( BBString *name,int *addr_type,int *addr_len ){
-	struct hostent *e=gethostbyname( bbTmpCString( name ) );
-	if( !e ) return 0;
-	*addr_type=e->h_addrtype;
-	*addr_len=e->h_length;
-	return e->h_addr_list;
-}
+BBARRAY getaddrinfo_(BBString *name, BBString *service, int family) {
+	struct addrinfo hints;
+	struct addrinfo * info;
+	struct addrinfo * ip;
+	
+	memset(&hints, 0, sizeof(struct addrinfo));
+	
+	char * n = bbStringToUTF8String(name);
+	char * s = 0;
+	if (service != &bbEmptyString) {
+		s = bbStringToUTF8String(service);
+	}
+	
+	hints.ai_family = bmx_stdc_convertAFFamily(family);
+	
+	int res = getaddrinfo(n, s, &hints, &info);
+	
+	bbMemFree(s);
+	bbMemFree(n);
+	
+	if (res != 0) {
+		return &bbEmptyArray;
+	}
+	
+	int count = 0;
+	for (ip = info; ip != NULL; ip = ip->ai_next) {
+		count++;
+	}
+	
+	BBArray * arr = pub_stdc_TAddrInfo__CreateArray(count);
 
-int connect_( int socket,const char *addr,int addr_type,int addr_len,int port ){
-	struct sockaddr_in sa;
+	count = 0;
+	for (ip = info; ip != NULL; ip = ip->ai_next) {
 
-	if( addr_type!=AF_INET ) return -1;
+		BBObject * obj = pub_stdc_TAddrInfo__Create(ip, count == 0);
+		
+		pub_stdc_TAddrInfo__SetAtIndex(arr, obj, count);
 
-		memset( &sa,0,sizeof(sa) );
-		sa.sin_family=addr_type;
-		sa.sin_port=htons( port );
-		memcpy( &sa.sin_addr,addr,addr_len );
-	
-		return connect( socket,(void*)&sa,sizeof(sa) );
+		count++;
 	}
 	
+	return arr; 
+
+}
+
+int connect_( int socket, struct addrinfo * info ){
+	return connect( socket, info->ai_addr, info->ai_addrlen);
+}
+
 int listen_( int socket,int backlog ){
 	return listen( socket,backlog );
 }
@@ -438,13 +501,31 @@ size_t send_( int socket,const char *buf,size_t size,int flags ){
 	return send( socket,buf,size,flags );
 }
 
-int sendto_( int socket,const char *buf,int size,int flags,int dest_ip,int dest_port ){
-	struct	sockaddr_in sa;
-	memset( &sa,0,sizeof(sa) );
-	sa.sin_family=AF_INET;
-	sa.sin_addr.s_addr=htonl( dest_ip );
-	sa.sin_port=htons( dest_port );
-	return sendto( socket,buf,size,flags,(void*)&sa,sizeof(sa));
+int sendto_( int socket,const char *buf,int size,int flags,const char * dest_ip,int dest_port, int addr_type ){
+	addr_type = bmx_stdc_convertAFFamily(addr_type);
+	
+	switch (addr_type) {
+		case AF_INET:
+		{
+			struct	sockaddr_in sa;
+			memset( &sa,0,sizeof(sa) );
+			sa.sin_family=AF_INET;
+			sa.sin_addr.s_addr=htonl( dest_ip );
+//			memcpy( &sa.sin_addr,dest_ip,4 );
+			sa.sin_port=htons( dest_port );
+			return sendto( socket,buf,size,flags,(void*)&sa,sizeof(sa));
+		}
+		case AF_INET6:
+		{
+			struct sockaddr_in6 sa;
+			memset( &sa,0,sizeof(sa) );
+			sa.sin6_family=AF_INET6;
+			sa.sin6_port=htons( dest_port );
+			memcpy( &sa.sin6_addr, dest_ip,16 );
+		
+			return sendto( socket,buf,size,flags,(void*)&sa,sizeof(sa));
+		}
+	}
 }
 
 size_t recv_( int socket,char *buf,size_t size,int flags ){
@@ -495,6 +576,76 @@ int strftime_( char *buf,int size,BBString *fmt,void *ttime ){
 	return strftime( buf,size,bbTmpCString(fmt),ttime );
 }
 
+int bmx_stdc_addrinfo_flags(struct addrinfo * info) {
+	return info->ai_flags;
+}
+
+int bmx_stdc_addrinfo_family(struct addrinfo * info) {
+	return info->ai_family;
+}
+
+int bmx_stdc_addrinfo_socktype(struct addrinfo * info) {
+	return info->ai_socktype;
+}
+
+int bmx_stdc_addrinfo_protocol(struct addrinfo * info) {
+	return info->ai_protocol;
+}
+
+int bmx_stdc_addrinfo_addrlen(struct addrinfo * info) {
+	return info->ai_addrlen;
+}
+
+struct sockaddr * bmx_stdc_addrinfo_addr(struct addrinfo * info) {
+	return info->ai_addr;
+}
+
+BBString * bmx_stdc_addrinfo_canonname(struct addrinfo * info) {
+	return bbStringFromUTF8String(info->ai_canonname);
+}
+
+int bmx_stdc_convertNIFlags(int flags) {
+	int niFlags = 0;
+	
+	if (flags & 0x0001) {
+		niFlags |= NI_DGRAM;
+	}
+
+	if (flags & 0x0002) {
+		niFlags |= NI_NAMEREQD;
+	}
+
+	if (flags & 0x0004) {
+		niFlags |= NI_NOFQDN;
+	}
+
+	if (flags & 0x0008) {
+		niFlags |= NI_NUMERICHOST;
+	}
+
+	if (flags & 0x0010) {
+		niFlags |= NI_NUMERICSERV;
+	}
+	
+	return niFlags;
+}
+
+BBString * bmx_stdc_addrinfo_hostname(struct addrinfo * info, int flags) {
+	char host[256];
+	int res = getnameinfo(info->ai_addr, info->ai_addrlen, &host, 256, 0, 0, bmx_stdc_convertNIFlags(flags));
+	if (res != 0) {
+		return &bbEmptyString;
+	}
+	return bbStringFromUTF8String(host);
+}
+
+int inet_pton_(int family, BBString * src, void * dst) {
+	char * s = bbStringToCString(src);
+	int res = inet_pton(bmx_stdc_convertAFFamily(family), s, dst);
+	bbMemFree(s);
+	return res;
+}
+
 #if _WIN32
 
 static void CleanupWSA(){