Logo Search packages:      
Sourcecode: blender version File versions

v_network.c

/*
**
*/

#if defined _WIN32
#include <winsock.h>
typedef unsigned int uint;
typedef SOCKET VSocket;
#else
typedef int VSocket;
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#endif
#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint32;
typedef int int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char uint8;
typedef char int8;
typedef unsigned char boolean;

#include "v_cmd_gen.h"
#include "v_network.h"

#if !defined socklen_t
#define socklen_t int
#endif

#define     TRUE  1
#define     FALSE 0

typedef struct{
      struct sockaddr_in address;
      struct hostent *he;
} VNetworkConnection;

#define VERSE_STD_CONNECT_TO_PORT 4950

static VSocket    my_socket = -1;
static uint16     my_port = 0;

void v_n_set_port(unsigned short port)
{
      my_port = port;
}

VSocket v_n_socket_create(void)
{
      static boolean initialized = FALSE;
      struct sockaddr_in address;
        int buffer_size = 1 << 20;

      if(my_socket != -1)
            return my_socket;
#if defined _WIN32
      if(!initialized)
      {
            WSADATA wsaData;

            if(WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
            {
                  fprintf(stderr, "WSAStartup failed.\n");
                  exit(1);
            }

      }
#endif
      initialized = TRUE;
      if((my_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
            return -1;
#if defined _WIN32
      {
            unsigned long     one = 1UL;
            if(ioctlsocket(my_socket, FIONBIO, &one) != 0)
                  return -1;
      }
#else
      if(fcntl(my_socket, F_SETFL, O_NONBLOCK) != 0)
      {
            fprintf(stderr, "v_network: Couldn't make socket non-blocking\n");
            return -1;
      }
#endif
      address.sin_family = AF_INET;     /* host byte order */
      address.sin_port = htons(my_port); /* short, network byte order */
      address.sin_addr.s_addr = INADDR_ANY;
      if(bind(my_socket, (struct sockaddr *) &address, sizeof(struct sockaddr)) != 0)
      {
            fprintf(stderr, "v_network: Failed to bind(), code %d (%s)\n", errno, strerror(errno));
            exit(0); /* FIX ME */
      }
      if(setsockopt(my_socket, SOL_SOCKET, SO_SNDBUF, (const char *) &buffer_size, sizeof buffer_size) != 0)
            fprintf(stderr, "v_network: Couldn't set send buffer size of socket to %d\n", buffer_size);
      if(setsockopt(my_socket, SOL_SOCKET, SO_RCVBUF, (const char *) &buffer_size, sizeof buffer_size) != 0)
            fprintf(stderr, "v_network: Couldn't set receive buffer size of socket to %d\n", buffer_size);
      return my_socket;
}

void v_n_socket_destroy(void)
{
#if defined _WIN32
      closesocket(my_socket);
#else
      close(my_socket);
#endif
      my_socket = -1;
}

boolean v_n_set_network_address(VNetworkAddress *address, const char *host_name)
{
      struct hostent    *he;
      char        *colon = NULL, *buf = NULL;
      boolean           ok = FALSE;

      v_n_socket_create();
      address->port = VERSE_STD_CONNECT_TO_PORT;
      /* If a port number is included, as indicated by a colon, we need to work a bit more. */
      if((colon = strchr(host_name, ':')) != NULL)
      {
            size_t      hl = strlen(host_name);

            if((buf = malloc(hl + 1)) != NULL)
            {
                  unsigned int      tp;

                  strcpy(buf, host_name);
                  colon = buf + (colon - host_name);
                  *colon = '\0';
                  host_name = buf;
                  if(sscanf(colon + 1, "%u", &tp) == 1)
                  {
                        address->port = (unsigned short) tp;
                        if(address->port != tp) /* Protect against overflow. */
                              host_name = NULL;
                  }
                  else
                        host_name = NULL; /* Protect against parse error. */
            }
            else
                  return FALSE;
      }
      if(host_name != NULL && (he = gethostbyname(host_name)) != NULL)
      {
            memcpy(&address->ip, he->h_addr_list[0], he->h_length);
            address->ip = ntohl(address->ip);
            ok = TRUE;
      }
      if(buf != NULL)
            free(buf);

      return ok;
}

int v_n_send_data(VNetworkAddress *address, const char *data, size_t length)
{
      struct sockaddr_in      address_in;
      VSocket                 sock;
      int               ret;

      if((sock = v_n_socket_create()) == -1 || length == 0)
            return 0;
      address_in.sin_family = AF_INET;     /* host byte order */
      address_in.sin_port = htons(address->port); /* short, network byte order */
      address_in.sin_addr.s_addr = htonl(address->ip);
      memset(&address_in.sin_zero, 0, sizeof address_in.sin_zero);
      ret = sendto(sock, data, length, 0, (struct sockaddr *) &address_in, sizeof(struct sockaddr_in));
      if(ret < 0)
            fprintf(stderr, "Socket sendto() of %u bytes failed, code %d (%s)\n", (unsigned int) length, errno, strerror(errno));
      return ret;
}

#if !defined V_GENERATE_FUNC_MODE

extern void *v_con_get_network_address_id(unsigned int id);
extern unsigned int v_con_get_network_address_count();

unsigned int v_n_wait_for_incoming(unsigned int microseconds) 
{
      struct timeval    tv;
      fd_set            fd_select;
      unsigned int      s1, f1, s2, f2;

      if(microseconds == 0)
            return 0;
      v_n_socket_create();
      tv.tv_sec  = microseconds / 1000000;
      tv.tv_usec = microseconds % 1000000;
      FD_ZERO(&fd_select);
      FD_SET(my_socket, &fd_select);
      v_n_get_current_time(&s1, &f1);
      select(1, &fd_select, NULL, NULL, &tv);
      v_n_get_current_time(&s2, &f2);
      return (unsigned int) (1000000 * (s2 - s1) + (1000000.0 / 0xffffffffu) * (long) (f2 - f1));     /* Must cast to (long) for f1 > f2 case! */
}

#endif

int v_n_receive_data(VNetworkAddress *address, char *data, size_t length)
{
      struct      sockaddr_in address_in;
      socklen_t from_length = sizeof address_in;
      size_t      len;

      if(v_n_socket_create() == -1)
            return 0;
      memset(&address_in, 0, sizeof address_in);
      address_in.sin_family = AF_INET;
      address_in.sin_port = htons(my_port); 
      address_in.sin_addr.s_addr = INADDR_ANY;
      len = recvfrom(v_n_socket_create(), data, length, 0, (struct sockaddr *) &address_in, &from_length);
      if(len > 0)
      {
            address->ip   = ntohl(address_in.sin_addr.s_addr);
            address->port = ntohs(address_in.sin_port);
      }
      return len;
}

#if defined _WIN32

void v_n_get_current_time(uint32 *seconds, uint32 *fractions)
{
      static LARGE_INTEGER frequency;
      static boolean init = FALSE;
      LARGE_INTEGER counter;

      if(!init)
      {
            init = TRUE;
            QueryPerformanceFrequency(&frequency);
      }

      QueryPerformanceCounter(&counter);
      if(seconds != NULL)
            *seconds = (uint32) (counter.QuadPart / frequency.QuadPart);
      if(fractions != NULL)
            *fractions = (uint32) ((0xffffffffUL * (counter.QuadPart % frequency.QuadPart)) / frequency.QuadPart);
}

#else

void v_n_get_current_time(uint32 *seconds, uint32 *fractions)
{
      struct timeval tv;

      gettimeofday(&tv, NULL);
      if(seconds != NULL)
          *seconds = tv.tv_sec;
      if(fractions != NULL)
            *fractions = tv.tv_usec * 1E-6 * (double) (uint32)~0;
}

#endif

void v_n_get_address_string(const VNetworkAddress *address, char *string)
{
      sprintf(string, "%u.%u.%u.%u:%u", address->ip >> 24, (address->ip >> 16) & 0xff,
            (address->ip >> 8) & 0xff, address->ip & 0xff, address->port);
}

Generated by  Doxygen 1.6.0   Back to index