embb_mtapi_network_socket.c 3.75 KB
Newer Older
1 2 3 4
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <embb_mtapi_network_socket.h>
#include <string.h>
5
#ifdef _WIN32
6
#include <WinSock2.h>
7 8 9 10 11 12 13 14 15 16 17
#else
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#endif
18 19 20 21 22 23 24 25 26 27 28 29 30 31

int embb_mtapi_network_socket_initialize(
  embb_mtapi_network_socket_t * that) {
  that->handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (INVALID_SOCKET == that->handle) {
    return 0;
  } else {
    return 1;
  }
}

void embb_mtapi_network_socket_finalize(
  embb_mtapi_network_socket_t * that) {
  if (INVALID_SOCKET != that->handle) {
32
#ifdef _WIN32
33
    closesocket(that->handle);
34 35 36
#else
    close(that->handle);
#endif
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
    that->handle = INVALID_SOCKET;
  }
}

int embb_mtapi_network_socket_bind_and_listen(
  embb_mtapi_network_socket_t * that,
  char const * host,
  uint16_t port) {
  struct sockaddr_in in_addr;
  int reuseaddr_on = 1;

  // addr reuse
  if (SOCKET_ERROR == setsockopt(that->handle, SOL_SOCKET, SO_REUSEADDR,
    (const char *)&reuseaddr_on, sizeof(reuseaddr_on))) {
    return 0;
  }

  // bind & listen
  memset(&in_addr, 0, sizeof(in_addr));
  in_addr.sin_family = AF_INET;
  in_addr.sin_addr.s_addr = (NULL == host) ?
    htonl(INADDR_ANY) : inet_addr(host);
  in_addr.sin_port = htons(port);

  if (SOCKET_ERROR == bind(that->handle, (struct sockaddr *) &in_addr,
    sizeof(in_addr))) {
    return 0;
  }

  if (SOCKET_ERROR == listen(that->handle, 5)) {
    return 0;
  }

70
  return 1;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
}

int embb_mtapi_network_socket_accept(
  embb_mtapi_network_socket_t * that,
  embb_mtapi_network_socket_t * sock) {
  sock->handle = accept(that->handle, NULL, NULL);
  if (INVALID_SOCKET == sock->handle) {
    return 0;
  } else {
    return 1;
  }
}

int embb_mtapi_network_socket_connect(
  embb_mtapi_network_socket_t * that,
  const char * host,
  uint16_t port) {
  struct sockaddr_in addr;

  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(host);
  addr.sin_port = htons(port);

  if (SOCKET_ERROR == connect(that->handle, (struct sockaddr *)&addr,
    sizeof(addr))) {
97
#ifdef _WIN32
98
    if (WSAEWOULDBLOCK != WSAGetLastError())
99 100 101
#else
    if (EAGAIN != errno)
#endif
102 103 104 105 106 107
      return 0;
  }

  return 1;
}

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
int embb_mtapi_network_socket_select(
  embb_mtapi_network_socket_t * that,
  int timeout
  ) {
  fd_set read_set;
  int max_fd;
  int err;
  struct timeval tv;
  tv.tv_sec = timeout / 1000;
  tv.tv_usec = timeout % 1000;

  FD_ZERO(&read_set);
  FD_SET(that->handle, &read_set);
  max_fd = that->handle;

  if (timeout >= 0) {
124
    err = select(max_fd + 1, &read_set, NULL, NULL, &tv);
125
  } else {
126
    err = select(max_fd + 1, &read_set, NULL, NULL, NULL);
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
  }
  if (0 == err) {
    // timeout
    return 0;
  }
  if (SOCKET_ERROR == err) {
    return 0;
  }

  if (FD_ISSET(that->handle, &read_set)) {
    return 1;
  }

  return 0;
}

143 144 145 146 147 148 149 150 151 152 153 154 155 156
int embb_mtapi_network_socket_sendbuffer(
  embb_mtapi_network_socket_t * that,
  embb_mtapi_network_buffer_t * buffer) {
  int result = send(that->handle, buffer->data, buffer->size, 0);
  if (result == buffer->size) {
    return buffer->size;
  } else {
    return 0;
  }
}

int embb_mtapi_network_socket_recvbuffer(
  embb_mtapi_network_socket_t * that,
  embb_mtapi_network_buffer_t * buffer) {
157
  int err;
158 159
#ifdef _WIN32
  u_long bytes_available = 0;
160
  if (0 != ioctlsocket(that->handle, FIONREAD, &bytes_available))
161 162 163 164
#else
  int bytes_available = 0;
  if (0 != ioctl(that->handle, FIONREAD, &bytes_available))
#endif
165 166 167
    return 0;
  if (buffer->capacity > (int)bytes_available)
    return 0;
168 169
  err = recv(that->handle, buffer->data, buffer->capacity, 0);
  if (err != buffer->capacity)
170 171 172 173
    return 0;
  buffer->size = buffer->capacity;
  return buffer->size;
}