38.1 Using Winsock with Other Components

The gethostname function in Winsock has been misprototyped. Additionally, novsock2.h contains noxious #defines when certain C++ class libraries and headers are in use. To combat these troubles, some adjustments have been made.

First, if you have been using novsock2.h with no trouble, continue to do so. Nothing changes for you.If, however, you are having trouble with the gethostname function or are experiencing difficulty with novsock2.h replacing various identifiers such as select seemingly randomly in your code, see the following:

38.1.1 gethostname Function

The second parameter in the standard prototype of the gethostname function has been corrected in the newest version of novsock2.h. The Single UNIX Specification defines the following prototype for gethostname:

  int gethostname( char *name, size_t maxlen );
  

The Winsock prototype uses an int for the data type of the second parameter.

To determine if you have the right version of novsock2.h, merely grep for the existence of STATIC_WS2BSD. If it is there, you have the newest version.

38.1.2 Identifier Replacement

If you are experiencing difficulty with novsock2.h replacing various identifiers in your code, a problem that affects at least one C++ class library we know about, a slightly different approach is needed that goes a bit beyond simply replacing the SDK header file. You must do the following:

  • Get the new novsock2.h header file

  • Define STATIC_WS2BSD in your code before including the new SDK header

      #define STATIC_WS2BSD
      #include <winsock/novsock2.h>
      
  • Static link a small replacement library in your application. The source code for this object is below. Copy the source code from this document into your own .c or assembly file—whatever best facilitates your development environment. We give the assembly code only because it reduces the call overhead presented by the C code. The assembly is written in CodeWarrior syntax.

Assembly

The assembly version is written in C for Metrowerks CodeWarrior. It should be clear from this C code exactly how to write this in MASM or other assembly directive.

  /*====================================================================
  =  Novell Software Development Kit
  =
  =  Copyright (C) 2005 Novell, Inc. All Rights Reserved.
  =
  =  This work is subject to U.S. and international copyright laws and
  =  treaties. Use and redistribution of this work is subject  to  the
  =  license  agreement accompanying  the  software  development kit
  =  (SDK) that contains this work. However, no part of this work may 
  =  be revised and/or  modified  without the prior  written consent 
  =  of Novell, Inc. Any use or exploitation of this work without 
  =  authorization could subject the perpetrator to criminal  and  civil
  =  liability.
  =
  =  Special object/library to be linked by an NLM that #defines
  =  STATIC_WS2BSD in place of the destructive re#definitions that
  =  novsock2.h performs.
  =
  =  This file is suitable for use within Metrowerks CodeWarrior and
  =  maybe other environments.
  =
  =  ws2bsd.c
  ======================================================================
  */
  
  // these are all the Winsock functions that emulate Berkeley...
  extern int   WS2_32_bind            ( ... );
  extern int   WS2_32_closesocket     ( ... );
  extern int   WS2_32_gethostbyaddr   ( ... );
  extern int   WS2_32_gethostbyname   ( ... );
  extern int   WS2_32_gethostname     ( ... );
  extern int   WS2_32_getpeername     ( ... );
  extern int   WS2_32_getprotobyname  ( ... );
  extern int   WS2_32_getprotobynumber( ... );
  extern int   WS2_32_getservbyname   ( ... );
  extern int   WS2_32_getservbyport   ( ... );
  extern int   WS2_32_getsockname     ( ... );
  extern int   WS2_32_getsockopt      ( ... );
  extern int   WS2_32_htonl           ( ... );
  extern int   WS2_32_htons           ( ... );
  extern int   WS2_32_inet_addr       ( ... );
  extern int   WS2_32_inet_ntoa       ( ... );
  extern int   WS2_32_ioctlsocket     ( ... );
  extern int   WS2_32_listen          ( ... );
  extern int   WS2_32_ntohl           ( ... );
  extern int   WS2_32_ntohs           ( ... );
  extern int   WS2_32_recv            ( ... );
  extern int   WS2_32_recvfrom        ( ... );
  extern int   WS2_32_select          ( ... );
  extern int   WS2_32_send            ( ... );
  extern int   WS2_32_sendto          ( ... );
  extern int   WS2_32_setsockopt      ( ... );
  extern int   WS2_32_shutdown        ( ... );
  extern int   WS2_32_socket          ( ... );
  
  // these are our internal prototypes to avoid a compiler warning...
  int __declspec(naked)   bind            ( ... );
  int __declspec(naked)   closesocket     ( ... );
  int __declspec(naked)   gethostbyaddr   ( ... );
  int __declspec(naked)   gethostbyname   ( ... );
  int __declspec(naked)   gethostname     ( ... );
  int __declspec(naked)   getpeername     ( ... );
  int __declspec(naked)   getprotobyname  ( ... );
  int __declspec(naked)   getprotobynumber( ... );
  int __declspec(naked)   getservbyname   ( ... );
  int __declspec(naked)   getservbyport   ( ... );
  int __declspec(naked)   getsockname     ( ... );
  int __declspec(naked)   getsockopt      ( ... );
  int __declspec(naked)   htonl           ( ... );
  int __declspec(naked)   htons           ( ... );
  int __declspec(naked)   inet_addr       ( ... );
  int __declspec(naked)   inet_ntoa       ( ... );
  int __declspec(naked)   ioctlsocket     ( ... );
  int __declspec(naked)   listen          ( ... );
  int __declspec(naked)   ntohl           ( ... );
  int __declspec(naked)   ntohs           ( ... );
  int __declspec(naked)   recv            ( ... );
  int __declspec(naked)   recvfrom        ( ... );
  int __declspec(naked)   select          ( ... );
  int __declspec(naked)   send            ( ... );
  int __declspec(naked)   sendto          ( ... );
  int __declspec(naked)   setsockopt      ( ... );
  int __declspec(naked)   shutdown        ( ... );
  int __declspec(naked)   socket          ( ... );
  
  // and these are our implementations...
  int __declspec(naked) bind ( ... )
  {
     __asm jmp WS2_32_bind;
  }
  
  int __declspec(naked) closesocket ( ... )
  {
     __asm jmp WS2_32_closesocket;
  }
  
  int __declspec(naked) gethostbyaddr ( ... )
  {
     __asm jmp WS2_32_gethostbyaddr;
  }
  
  int __declspec(naked) gethostbyname ( ... )
  {
     __asm jmp WS2_32_gethostbyname;
  }
  
  int __declspec(naked) gethostname ( ... )
  {
     __asm jmp WS2_32_gethostname;
  }
  
  int __declspec(naked) getpeername ( ... )
  {
     __asm jmp WS2_32_getpeername;
  }
  
  int __declspec(naked) getprotobyname ( ... )
  {
     __asm jmp WS2_32_getprotobyname;
  }
  
  int __declspec(naked) getprotobynumber ( ... )
  {
     __asm jmp WS2_32_getprotobynumber;
  }
  
  int __declspec(naked) getservbyname ( ... )
  {
     __asm jmp WS2_32_getservbyname;
  }
  
  int __declspec(naked) getservbyport ( ... )
  {
     __asm jmp WS2_32_getservbyport;
  }
  
  int __declspec(naked) getsockname ( ... )
  {
     __asm jmp WS2_32_getsockname;
  }
  
  int __declspec(naked) getsockopt ( ... )
  {
     __asm jmp WS2_32_getsockopt;
  }
  
  int __declspec(naked) htonl ( ... )
  {
     __asm jmp WS2_32_htonl;
  }
  
  int __declspec(naked) htons ( ... )
  {
     __asm jmp WS2_32_htons;
  }
  
  int __declspec(naked) inet_addr ( ... )
  {
     __asm jmp WS2_32_inet_addr;
  }
  
  int __declspec(naked) inet_ntoa ( ... )
  {
     __asm jmp WS2_32_inet_ntoa;
  }
  
  int __declspec(naked) ioctlsocket ( ... )
  {
     __asm jmp WS2_32_ioctlsocket;
  }
  
  int __declspec(naked) listen ( ... )
  {
     __asm jmp WS2_32_listen;
  }
  
  int __declspec(naked) ntohl ( ... )
  {
     __asm jmp WS2_32_ntohl;
  }
  
  int __declspec(naked) ntohs ( ... )
  {
     __asm jmp WS2_32_ntohs;
  }
  
  int __declspec(naked) recv ( ... )
  {
     __asm jmp WS2_32_recv;
  }
  
  int __declspec(naked) recvfrom ( ... )
  {
     __asm jmp WS2_32_recvfrom;
  }
  
  int __declspec(naked) select(...)
  {
     __asm jmp WS2_32_select;
  }
  
  int __declspec(naked) send ( ... )
  {
     __asm jmp WS2_32_send;
  }
  
  int __declspec(naked) sendto ( ... )
  {
     __asm jmp WS2_32_sendto;
  }
  
  int __declspec(naked) setsockopt ( ... )
  {
     __asm jmp WS2_32_setsockopt;
  }
  
  int __declspec(naked) shutdown ( ... )
  {
     __asm jmp WS2_32_shutdown;
  }
  
  int __declspec(naked) socket ( ... )
  {
     __asm jmp WS2_32_socket;
  }
  

C

The C code for environments not supporting __declspec(naked) and __asm as is used in the preceeding CodeWarrior example.

  /*====================================================================
  =  Novell Software Development Kit
  =
  =  Copyright (C) 2005 Novell, Inc. All Rights Reserved.
  =
  =  This work is subject to U.S. and international copyright laws and
  =  treaties. Use and redistribution of this work is subject to the
  =  license  agreement accompanying the software  evelopment kit (SDK)
  =  that contains this work. However, no part of this work may be
  =  revised and/or  modified  without  the prior written consent of
  =  Novell, Inc. Any use or exploitation of this work without 
  =  authorization could subject the perpetrator to criminal and civil
  =  liability.
  =
  =  Special object/library to be linked by an NLM  that  #defines
  =  STATIC_WS2BSD to eliminate the destructive re#definitions that
  =  novsock2.h performs otherwise.
  =
  =  ws2bsd.c
  ======================================================================
  */
  #include <netdb.h>
  #include <unistd.h>
  #include <sys/socket.h>
  #include <sys/select.h>
  #include <arpa/inet.h>
  #include <netinet/in.h>
  
  // missing prototypes for functions here...
  int   closesocket( int socket );
  
  // prototypes from Winsock2 (we won’t include novsock2.h here)...
  uint32_t   WS2_32_htonl( uint32_t hostlong );
  uint16_t   WS2_32_htons( uint16_t hostshort );
  uint32_t   WS2_32_ntohl( uint32_t netlong );
  uint16_t   WS2_32_ntohs( uint16_t netshort );
  uint32_t   WS2_32_ntohl( uint32_t netlong );
  int        WS2_32_bind( int socket, const struct sockaddr *address,
                       socklen_t address_len );
  ssize_t    WS2_32_recvfrom( int socket, void *buffer, size_t length,
                       int flags, struct sockaddr *address,
                       socklen_t *address_len );
  ssize_t   WS2_32_recv( int socket, void *buffer, size_t length,
                       int flags );
  ssize_t   WS2_32_send( int socket, const void *buffer, size_t length,
                       int flags);
  ssize_t   WS2_32_sendto( int socket, const void *message,
                       size_t length, int flags,
                       const struct sockaddr *dest_addr,
                       socklen_t dest_len );
  int      WS2_32_listen( int socket, int backlog );
  int      WS2_32_getpeername( int socket, struct sockaddr *address,
                       socklen_t *address_len );
  int      WS2_32_getsockname( int socket, struct sockaddr *address,
                       socklen_t *address_len );
  int      WS2_32_getsockopt( int socket, int level, int option_name,
                       void *option_value, socklen_t *option_len );
  struct hostent  *WS2_32_gethostbyaddr( const void *addr, 
                       socklen_t len, int type );
  struct hostent  *WS2_32_gethostbyname( const char *name );
  struct protoent *WS2_32_getprotobyname( const char *name );
  struct protoent *WS2_32_getprotobynumber( int proto );
  int              WS2_32_gethostname( char *name, size_t namelen );
  struct servent  *WS2_32_getservbyname( const char *name, const char *proto );
  struct servent  *WS2_32_getservbyport( int port, const char *proto );
  in_addr_t        WS2_32_inet_addr( const char *cp );
  char            *WS2_32_inet_ntoa( struct in_addr in );
  int              WS2_32_socket( int domain, int type, int protocol );
  int              WS2_32_closesocket( int socket );
  int              WS2_32_shutdown( int socket, int how );
  int       WS2_32_select( int nfds, fd_set *readfds, fd_set *writefds,
                       fd_set *errorfds, const struct timeval *timeout );
  
  
  uint32_t htonl
  (
     uint32_t hostlong
  )
  {
     return WS2_32_htonl(hostlong);
  }
  
  uint16_t htons
  (
     uint16_t hostshort
  )
  {
     return WS2_32_htons(hostshort);
  }
  
  uint32_t ntohl
  (
     uint32_t netlong
  )
  {
     return WS2_32_ntohl(netlong);
  }
  
  uint16_t ntohs
  (
     uint16_t netshort
  )
  {
     return WS2_32_ntohs(netshort);
  }
  
  int bind
  (
     int                   socket,
     const struct sockaddr *address,
     socklen_t             address_len
  )
  {
     return WS2_32_bind(socket, address, address_len);
  }
  
  ssize_t recvfrom
  (
     int             socket,
     void            *buffer,
     size_t          length,
     int             flags,
     struct sockaddr *address,
     socklen_t       *address_len
  )
  {
     return WS2_32_recvfrom(socket, buffer, length, flags, address,
             address_len);
  }
  
  ssize_t recv
  (
     int    socket,
     void   *buffer,
     size_t length,
     int    flags
  )
  {
     return WS2_32_recv(socket, buffer, length, flags);
  }
  
  ssize_t send
  (
     int        socket,
     const void *buffer,
     size_t     length,
     int        flags
  )
  {
     return WS2_32_send(socket, buffer, length, flags);
  }
  
  ssize_t sendto
  (
     int                   socket,
     const void            *message,
     size_t                length,
     int                   flags,
     const struct sockaddr *dest_addr,
     socklen_t             dest_len
  )
  {
     return WS2_32_sendto(socket, message, length, flags, dest_addr,
                          dest_len);
  }
  
  int listen
  (
     int socket,
     int backlog
  )
  {
     return WS2_32_listen(socket, backlog);
  }
  
  int getpeername
  (
     int             socket,
     struct sockaddr *address,
     socklen_t       *address_len
  )
  {
     return WS2_32_getpeername(socket, address, address_len);
  }
  
  int getsockname
  (
     int             socket,
     struct sockaddr *address,
     socklen_t       *address_len
  )
  {
     return WS2_32_getsockname(socket, address, address_len);
  }
  
  int getsockopt
  (
     int       socket,
     int       level,
     int       option_name,
     void      *option_value,
     socklen_t *option_len
  )
  {
     return WS2_32_getsockopt(socket, level, option_name, option_value,
                option_len);
  }
  
  struct hostent *gethostbyaddr
  (
     const char *addr,
     socklen_t  len,
     int        type
  )
  {
     return WS2_32_gethostbyaddr(addr, len, type);
  }
  
  struct hostent *gethostbyname
  (
     const char *name
  )
  {
     return WS2_32_gethostbyname(name);
  }
  
  struct protoent *getprotobyname
  (
     const char *name
  )
  {
     return WS2_32_getprotobyname(name);
  }
  
  struct protoent *getprotobynumber
  (
     int proto
  )
  {
     return WS2_32_getprotobynumber(proto);
  }
  
  int gethostname
  (
     char   *name,
     size_t namelen
  )
  {
     return WS2_32_gethostname(name, namelen);
  }
  
  struct servent *getservbyname
  (
     const char *name,
     const char *proto
  )
  {
     return WS2_32_getservbyname(name, proto);
  }
  
  struct servent *getservbyport
  (
     int        port,
     const char *proto
  )
  {
     return WS2_32_getservbyport(port, proto);
  }
  
  in_addr_t inet_addr
  (
     const char *cp
  )
  {
     return WS2_32_inet_addr(cp);
  }
  
  char *inet_ntoa
  (
     struct in_addr  in
  )
  {
     return WS2_32_inet_ntoa(in);
  }
  
  int socket
  (
     int domain,
     int type,
     int protocol
  )
  {
     return WS2_32_socket(domain, type, protocol);
  }
  
  int closesocket
  (
     int socket
  )
  {
     return WS2_32_closesocket(socket);
  }
  
  int shutdown
  (
     int socket,
     int how
  )
  {
     return WS2_32_shutdown(socket, how);
  }
  
  int select
  (
     int                  nfds,
     fd_set               *readfds,
     fd_set               *writefds,
     fd_set               *errorfds,
     const struct timeval *timeout
  )
  {
     return WS2_32_select(nfds, readfds, writefds, errorfds, timeout);
  }