Home | History | Annotate | Download | only in util
      1 
      2 #include "pipe/p_compiler.h"
      3 #include "util/u_network.h"
      4 #include "util/u_debug.h"
      5 #include "util/u_string.h"
      6 
      7 #include <stdio.h>
      8 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
      9 #  include <winsock2.h>
     10 #  include <windows.h>
     11 #  include <ws2tcpip.h>
     12 #elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || \
     13    defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN) || defined(PIPE_OS_SOLARIS)
     14 #  include <sys/socket.h>
     15 #  include <netinet/in.h>
     16 #  include <unistd.h>
     17 #  include <fcntl.h>
     18 #  include <netdb.h>
     19 #else
     20 #  warning "No socket implementation"
     21 #endif
     22 
     23 boolean
     24 u_socket_init()
     25 {
     26 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
     27    WORD wVersionRequested;
     28    WSADATA wsaData;
     29    int err;
     30 
     31    /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
     32    wVersionRequested = MAKEWORD(1, 1);
     33 
     34    err = WSAStartup(wVersionRequested, &wsaData);
     35    if (err != 0) {
     36       debug_printf("WSAStartup failed with error: %d\n", err);
     37       return FALSE;
     38    }
     39    return TRUE;
     40 #elif defined(PIPE_HAVE_SOCKETS)
     41    return TRUE;
     42 #else
     43    return FALSE;
     44 #endif
     45 }
     46 
     47 void
     48 u_socket_stop()
     49 {
     50 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
     51    WSACleanup();
     52 #endif
     53 }
     54 
     55 void
     56 u_socket_close(int s)
     57 {
     58    if (s < 0)
     59       return;
     60 
     61 #if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
     62     || defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
     63    shutdown(s, SHUT_RDWR);
     64    close(s);
     65 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
     66    shutdown(s, SD_BOTH);
     67    closesocket(s);
     68 #else
     69    assert(0);
     70 #endif
     71 }
     72 
     73 int u_socket_accept(int s)
     74 {
     75 #if defined(PIPE_HAVE_SOCKETS)
     76    return accept(s, NULL, NULL);
     77 #else
     78    return -1;
     79 #endif
     80 }
     81 
     82 int
     83 u_socket_send(int s, void *data, size_t size)
     84 {
     85 #if defined(PIPE_HAVE_SOCKETS)
     86    return send(s, data, size, 0);
     87 #else
     88    return -1;
     89 #endif
     90 }
     91 
     92 int
     93 u_socket_peek(int s, void *data, size_t size)
     94 {
     95 #if defined(PIPE_HAVE_SOCKETS)
     96    return recv(s, data, size, MSG_PEEK);
     97 #else
     98    return -1;
     99 #endif
    100 }
    101 
    102 int
    103 u_socket_recv(int s, void *data, size_t size)
    104 {
    105 #if defined(PIPE_HAVE_SOCKETS)
    106    return recv(s, data, size, 0);
    107 #else
    108    return -1;
    109 #endif
    110 }
    111 
    112 int
    113 u_socket_connect(const char *hostname, uint16_t port)
    114 {
    115 #if defined(PIPE_HAVE_SOCKETS)
    116    int s, r;
    117    struct addrinfo hints, *addr;
    118    char portString[20];
    119 
    120    memset(&hints, 0, sizeof hints);
    121    hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
    122    hints.ai_socktype = SOCK_STREAM;
    123 
    124    util_snprintf(portString, sizeof(portString), "%d", port);
    125 
    126    r = getaddrinfo(hostname, portString, NULL, &addr);
    127    if (r != 0) {
    128       return -1;
    129    }
    130 
    131    s = socket(addr->ai_family, SOCK_STREAM, IPPROTO_TCP);
    132    if (s < 0) {
    133       freeaddrinfo(addr);
    134       return -1;
    135    }
    136 
    137    if (connect(s, addr->ai_addr, (int) addr->ai_addrlen)) {
    138       u_socket_close(s);
    139       freeaddrinfo(addr);
    140       return -1;
    141    }
    142 
    143    freeaddrinfo(addr);
    144 
    145    return s;
    146 #else
    147    assert(0);
    148    return -1;
    149 #endif
    150 }
    151 
    152 int
    153 u_socket_listen_on_port(uint16_t portnum)
    154 {
    155 #if defined(PIPE_HAVE_SOCKETS)
    156    int s;
    157    struct sockaddr_in sa;
    158    memset(&sa, 0, sizeof(struct sockaddr_in));
    159 
    160    sa.sin_family = AF_INET;
    161    sa.sin_port = htons(portnum);
    162 
    163    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    164    if (s < 0)
    165       return -1;
    166 
    167    if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) {
    168       u_socket_close(s);
    169       return -1;
    170    }
    171 
    172    listen(s, 0);
    173 
    174    return s;
    175 #else
    176    assert(0);
    177    return -1;
    178 #endif
    179 }
    180 
    181 void
    182 u_socket_block(int s, boolean block)
    183 {
    184 #if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
    185     || defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
    186    int old = fcntl(s, F_GETFL, 0);
    187    if (old == -1)
    188       return;
    189 
    190    /* TODO obey block */
    191    if (block)
    192       fcntl(s, F_SETFL, old & ~O_NONBLOCK);
    193    else
    194       fcntl(s, F_SETFL, old | O_NONBLOCK);
    195 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
    196    u_long iMode = block ? 0 : 1;
    197    ioctlsocket(s, FIONBIO, &iMode);
    198 #else
    199    assert(0);
    200 #endif
    201 }
    202