diff --git a/artnet/artnet.c b/artnet/artnet.c index e3c3a1f..67e846d 100644 --- a/artnet/artnet.c +++ b/artnet/artnet.c @@ -103,7 +103,7 @@ artnet_node artnet_new(const char *ip, int verbose) { n->peering.peer = NULL; n->peering.master = TRUE; - n->sd = -1; + n->sd = INVALID_SOCKET; if (artnet_net_init(n, ip)) { free(n); @@ -176,32 +176,25 @@ int artnet_start(artnet_node vn) { /* - * Stops the ArtNet node - * Closes the network sockets held by the node - * + * Stops the ArtNet node. This closes the network sockets held by the node * @param vn the artnet_node - * @return 0 on success, -1 on failure + * @return 0 on success, non-0 on failure */ int artnet_stop(artnet_node vn) { node n = (node) vn; - int ret; - check_nullnode(vn); if (n->state.mode != ARTNET_ON) return ARTNET_EACTION; - if ((ret = artnet_net_close(n))) - return ret; - + artnet_net_close(n->sd); n->state.mode = ARTNET_STANDBY; return ARTNET_EOK; } -/** + +/* * Free the memory associated with this node - * - * */ int artnet_destroy(artnet_node vn) { node n = (node) vn; diff --git a/artnet/network.c b/artnet/network.c index 6795485..535f1e5 100644 --- a/artnet/network.c +++ b/artnet/network.c @@ -72,6 +72,12 @@ static void free_ifaces(iface_t *head) { } } +#ifdef WIN32 + + + +# else // not WIN32 + #ifdef USE_GETIFADDRS /* @@ -172,7 +178,7 @@ static int get_ifaces(iface_t **ift_head_r) { return 0; } -#else +#else // no GETIFADDRS /* * @@ -235,14 +241,11 @@ static int get_ifaces(iface_t **ift_head_r) { // loop through each iface for (ptr = buf; ptr < buf + ifc.ifc_len;) { - ifr = (struct ifreq*) ptr; // work out length here #ifdef HAVE_SOCKADDR_SA_LEN - len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); - #else switch (ifr->ifr_addr.sa_family) { #ifdef IPV6 @@ -341,7 +344,8 @@ static int get_ifaces(iface_t **ift_head_r) { return ret; } -#endif +#endif // GETIFADDRS +#endif // not WIN32 /* @@ -418,21 +422,29 @@ e_return : * */ int artnet_net_start(node n) { + int sock; struct sockaddr_in servAddr; - int bcast_flag = TRUE; + int true_flag = TRUE; node tmp; - int ret = ARTNET_EOK; - // only attempt to bind to the broadcast if we are the group master + // only attempt to bind if we are the group master if (n->peering.master == TRUE) { - /* create socket */ - n->sd = socket(PF_INET, SOCK_DGRAM, 0); +#ifdef WIN32 + // check winsock version + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData); != 0) + return (-1); + if (wsaData.wVersion != wVersionRequested) + return (-2); +#endif - if (n->sd < 0) { - artnet_error("Could not create socket %s", strerror(errno)); - ret = ARTNET_ENET; - goto e_socket1; + // create socket + sock = socket(PF_INET, SOCK_DGRAM, 0); + + if (sock < 0) { + artnet_error("Could not create socket %s", artnet_net_last_error()); + return ARTNET_ENET; } memset(&servAddr, 0x00, sizeof(servAddr)); @@ -441,47 +453,59 @@ int artnet_net_start(node n) { servAddr.sin_addr.s_addr = htonl(INADDR_ANY); if (n->state.verbose) - printf("Binding to %s \n" , inet_ntoa(servAddr.sin_addr)); + printf("Binding to %s \n", inet_ntoa(servAddr.sin_addr)); - /* bind sockets - * we do one for the ip address and one for the broadcast address - */ - if (bind(n->sd, (SA *) &servAddr, sizeof(servAddr)) == -1) { - artnet_error("Failed to bind to socket %s", strerror(errno)); - ret = ARTNET_ENET; - goto e_bind1; + // bind sockets + if (bind(sock, (SA *) &servAddr, sizeof(servAddr)) == -1) { + artnet_error("Failed to bind to socket %s", artnet_net_last_error()); + artnet_net_close(sock); + return ARTNET_ENET; } // allow bcasting - if (setsockopt(n->sd, + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, - (char*) &bcast_flag, // char* for win32 + (char*) &true_flag, // char* for win32 sizeof(int)) == -1) { - artnet_error("Failed to bind to socket %s", strerror(errno)); - ret = ARTNET_ENET; - goto e_setsockopt; + artnet_error("Failed to bind to socket %s", artnet_net_last_error()); + artnet_net_close(sock); + return ARTNET_ENET; } - // now we need to propagate the sd to all our peers - for (tmp = n->peering.peer; tmp != NULL && tmp != n; - tmp = tmp->peering.peer) - tmp->sd = n->sd; - } +#ifdef WIN32 + // ### LH - 22.08.2008 + // make it possible to reuse port, if SO_REUSEADDR + // exists on operating system - return ARTNET_EOK; + // NEVER USE SO_EXCLUSIVEADDRUSE, as that freezes the application + // on WinXP, if port is in use ! + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &true_flag, + sizeof(true_flag)) < 0) { + + artnet_error("Set reuse failed", artnet_net_last_error()); + artnet_net_close(sock); + return ARTNET_ENET; + } -e_setsockopt: -e_bind1: - close(n->sd); + if (SOCKET_ERROR == ioctlsocket(n->sd, FIONBIO, &true_flag)) { + artnet_error("ioctlsocket", artnet_net_last_error()); + artnet_net_close(sock); + return ARTNET_ENET; + } +#endif -e_socket1: - return ret; + n->sd = sock; + // Propagate the socket to all our peers + for (tmp = n->peering.peer; tmp && tmp != n; tmp = tmp->peering.peer) + tmp->sd = sock; + } + return ARTNET_EOK; } /* - * Recv a packet from the network + * Receive a packet. */ int artnet_net_recv(node n, artnet_packet p, int delay) { ssize_t len; @@ -505,7 +529,7 @@ int artnet_net_recv(node n, artnet_packet p, int delay) { break; case -1: if ( errno != EINTR) { - artnet_error("%s : select error", __FUNCTION__); + artnet_error("Select error %s", artnet_net_last_error()); return ARTNET_ENET; } return ARTNET_EOK; @@ -524,7 +548,7 @@ int artnet_net_recv(node n, artnet_packet p, int delay) { (SA*) &cliAddr, &cliLen); if (len < 0) { - artnet_error("%s : recvfrom error %s", __FUNCTION__, strerror(errno)); + artnet_error("Recvfrom error %s", artnet_net_last_error()); return ARTNET_ENET; } @@ -569,7 +593,7 @@ int artnet_net_send(node n, artnet_packet p) { (SA*) &addr, sizeof(addr)); if (ret == -1) { - artnet_error("Sendto failed: %s", strerror(errno)); + artnet_error("Sendto failed: %s", artnet_net_last_error()); n->state.report_code = ARTNET_RCUDPFAIL; return ARTNET_ENET; @@ -579,7 +603,7 @@ int artnet_net_send(node n, artnet_packet p) { return ARTNET_ENET; } - if (n->callbacks.send.fh != NULL) { + if (n->callbacks.send.fh) { get_type(p); n->callbacks.send.fh(n, p, n->callbacks.send.data); } @@ -615,12 +639,22 @@ int artnet_net_set_fdset (node n, fd_set *fdset) { } -int artnet_net_close(node n) { - if (close(n->sd)) { - artnet_error(strerror(errno)); +/* + * Close a socket + */ +int artnet_net_close(int sock) { +#ifdef WIN32 + shutdown(sock, SD_BOTH); + closesocket(sock); + WSACancelBlockingCall(); + WSACleanup(); +#else + if (close(sock)) { + artnet_error(artnet_net_last_error()); return ARTNET_ENET; } return ARTNET_EOK; +#endif } @@ -640,3 +674,18 @@ int artnet_net_inet_aton(const char *ip_address, struct in_addr *address) { return ARTNET_EOK; } + +/* + * + */ +const char *artnet_net_last_error() { +#ifdef WIN32 + static char[10] error_str; + int error = WSAGetLastError(); + snprintf(error_str, sizeof(error_str) "%d", error); + return error_str; +#else + return strerror(errno); +#endif +} + diff --git a/artnet/private.h b/artnet/private.h index 19c83f0..4b12ded 100644 --- a/artnet/private.h +++ b/artnet/private.h @@ -95,6 +95,10 @@ extern uint16_t HIGH_BYTE; #define max(a, b) ((a) > (b) ? (a) : (b)) #endif +#ifndef INVALID_SOCKET +#define INVALID_SOCKET -1 +#endif + // byte ordering macros #define bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) @@ -488,9 +492,10 @@ int artnet_net_send(node n, artnet_packet p); int artnet_net_set_non_block(node n); int artnet_net_init(node n, const char *ip); int artnet_net_start(node n); -int artnet_net_close(node n); +int artnet_net_close(int sock); int artnet_net_join(node n1, node n2); int artnet_net_set_fdset(node n, fd_set *fdset); int artnet_net_inet_aton(const char *ip_address, struct in_addr *address); +const char *artnet_net_last_error(); #endif