[icecast-dev] Submission: Patch to libshout/sock.c for MacOSX

SKoT McDonald skot at tomandandy.com
Tue Nov 13 15:05:24 PST 2001



Hi,

re libshout:
MacOSX doesn't have poll(), which prevents sock.c from
compiling. I've patched sock.c to use select(), which is
supported on MacOSX, and should be elsewhere too.

I've marked my changes with "SKoT" comments in the file below.
Main changes are in sock_write_bytes().

- SKoT

------8<-----

/* sock.c
 * - General Socket Functions
 *
 * Copyright (c) 1999 Jack Moffitt, Barath Raghavan, and Alexander Haväng
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
USA.
 *
 */

#ifdef HAVE_CONFIG_H
#ifdef _WIN32
#include <win32config.h>
#else
#include <config.h>
#endif
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>    // - SKoT
#include <sys/types.h>
// #include <sys/poll.h> // - SKoT
#include <ctype.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <string.h>
#include <errno.h>
#include <fcntl.h>

#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>
#else
#include <winsock.h>
#endif

#ifndef HAVE_SOCKLEN_T
#define socklen_t int
#endif

#ifndef _WIN32
extern int h_errno, errno;
#endif

#include "sock.h"

int sock_recoverable(int error)
{
 if (error == EAGAIN || error == EINTR || error == EINPROGRESS || error ==
EWOULDBLOCK) {
  return 1;
 }

 return 0;
}

int sock_valid_socket(SOCKET sockfd)
{
 return (sockfd >= 0);
}

#ifdef _WIN32
int inet_aton(const char *s, struct in_addr *a)
{
 int lsb, b2, b3, msb;

 if (sscanf(s, "%d.%d.%d.%d", &lsb, &b2, &b3, &msb) < 4) {
  return 0;
 }

#ifdef HAVE_INET_ADDR
 a->s_addr = inet_addr(s);

 if(a->s_addr == -1)
  return 0;
#else
 a->s_addr = lsb + (b2 << 8) + (b3 << 16) + (msb << 24);
#endif

 return 1;
}
#endif /* _WIN32 */

int sock_set_blocking(SOCKET sockfd, const int block)
{
#ifdef _WIN32
 int varblock = block;
#endif

 if ((!sock_valid_socket(sockfd)) || (block < 0) || (block > 1))
  return SOCKET_ERROR;

#ifdef _WIN32
 return ioctlsocket(sockfd, FIONBIO, &varblock);
#else
 return fcntl(sockfd, F_SETFL, (block == SOCK_BLOCK) ? 0 : O_NONBLOCK);
#endif
}

int sock_close(SOCKET sockfd)
{
#ifdef _WIN32
 return closesocket(sockfd);
#else
 return close(sockfd);
#endif
}

/*
 *  Write len bytes from buf to the socket.
 */
int sock_write_bytes(SOCKET sockfd, const char *buff, const int len)
{
 int wrote, res, polled;
// struct pollfd socks;           // <SKoT>
        fd_set  writefds;              //
        struct timeval timeout;        // </SKoT>

 /* sanity check */
 if (!buff) {
  return SOCKET_ERROR;
 } else if (len <= 0) {
  return SOCKET_ERROR;
 } else if (!sock_valid_socket(sockfd)) {
  return SOCKET_ERROR;
 }

 FD_ZERO(&writefds);             // <SKoT>
        FD_SET(sockfd, &writefds);      //
// socks.fd = sockfd;              //
// socks.events = POLLOUT;         //
        timeout.tv_sec  = 0;            //
 timeout.tv_usec = 1000;         // </SKoT>

 wrote = 0;
 while (wrote < len) {

                // SKoT: replaced poll with select

  polled = select(sockfd+1, 0, &writefds, 0, &timeout);
                // polled = poll(socks, 1, 30000);

  if ((polled == -1) && sock_recoverable(errno))
   continue;
  if (polled != 1)
   return SOCKET_ERROR;

  res = send(sockfd, &buff[wrote], len - wrote, 0);

  if ((res < 0) && (!sock_recoverable(errno)))
   return SOCKET_ERROR;
  if (res > 0)
   wrote += res;
 }

 return wrote;
}

/*
 *  Write a string to a socket.
 */
int sock_write_string(SOCKET sockfd, const char *buff)
{
 return (sock_write_bytes(sockfd, buff, strlen(buff)) > 0);
}

/*
 * Write a printf() style formatted message to the socket
 * Return 1 if all bytes where successfully written, and 0 if not.
 * Potential problems: Will truncate the string if longer than 1024 bytes.
 *                     Might fuck everything up if no vsnprintf is available
 */
int sock_write(SOCKET sockfd, const char *fmt, ...)
{
 char buff[1024];
 va_list ap;

 va_start(ap, fmt);
#ifdef HAVE_VSNPRINTF
 vsnprintf(buff, 1024, fmt, ap);
#else
 vsprintf(buff, fmt, ap);
#endif
 va_end(ap);

 return (sock_write_bytes(sockfd, buff, strlen(buff)) > 0);
}

/*
 * Read one line of at max len bytes from sockfd into buff.
 * If ok, return 1 and nullterminate buff. Otherwize return 0.
 * Terminating \n is not put into the buffer.
 * Assert Class: 2
 */
int sock_read_line(SOCKET sockfd, char *buff, const int len)
{
 char c = '\0';
 int read_bytes, pos;

 if (!sock_valid_socket(sockfd)) {
  return 0;
 } else if (!buff) {
  return 0;
 } else if (len <= 0) {
  return 0;
 }

 pos = 0;
 read_bytes = recv(sockfd, &c, 1, 0);

 if (read_bytes < 0) {
  return 0;
 }

 while ((c != '\n') && (pos < len) && (read_bytes == 1)) {
  if (c != '\r')
   buff[pos++] = c;
  read_bytes = recv(sockfd, &c, 1, 0);
 }

 if (read_bytes == 1) {
  buff[pos] = '\0';
  return 1;
 } else {
  return 0;
 }
}

/*
 * Connect to hostname on specified port and return the created socket.
 */
SOCKET sock_connect_wto(const char *hostname, const int port, const int
timeout)
{
 SOCKET sockfd;
 struct sockaddr_in sin, server;

 if (!hostname || !hostname[0]) {
  return INVALID_SOCKET;
 } else if (port <= 0) {
  return INVALID_SOCKET;
 }

 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd == INVALID_SOCKET) {
  sock_close(sockfd);
  return INVALID_SOCKET;
 }

 memset(&sin, 0, sizeof(sin));
 memset(&server, 0, sizeof(struct sockaddr_in));

 if (inet_aton(hostname, (struct in_addr *)&sin.sin_addr) == 0) {
  sock_close(sockfd);
  return INVALID_SOCKET;
 }

 memcpy(&server.sin_addr, &sin.sin_addr, sizeof(sin));

 server.sin_family = AF_INET;
 server.sin_port = htons(port);

 /* if we have a timeout, use select, if not, use connect straight. */
 /* dunno if this is portable, and it sure is complicated for such a
    simple thing to want to do.  damn BSD sockets! */
 if (timeout > 0) {
  fd_set wfds;
  struct timeval tv;
  int retval;
  int val;
  socklen_t valsize = sizeof(int);

  FD_ZERO(&wfds);
  FD_SET(sockfd, &wfds);
  tv.tv_sec = timeout;
  tv.tv_usec = 0;

  sock_set_blocking(sockfd, SOCK_NONBLOCK);
  retval = connect(sockfd, (struct sockaddr *)&server, sizeof(server));
  if (retval == 0) {
   sock_set_blocking(sockfd, SOCK_BLOCK);
   return sockfd;
  } else {
#ifdef _WIN32
   if (WSAGetLastError() == WSAEINPROGRESS) {
#else
   if (!sock_recoverable(errno)) {
#endif
    sock_close(sockfd);
    return SOCKET_ERROR;
   }
  }

  if (select(sockfd + 1, NULL, &wfds, NULL, &tv)) {
   retval = getsockopt (sockfd, SOL_SOCKET, SO_ERROR, (void *)&val,
(socklen_t *)&valsize);
   if ((retval == 0) && (val == 0)) {
    sock_set_blocking(sockfd, SOCK_BLOCK);
    return sockfd;
   } else {
    sock_close(sockfd);
    return SOCKET_ERROR;
   }
  } else {
   sock_close(sockfd);
   return SOCKET_ERROR;
  }
       } else {
    if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) == 0) {
   return sockfd;
  } else {
   sock_close(sockfd);
   return SOCKET_ERROR;
  }
       }
}

--- >8 ----
List archives:  http://www.xiph.org/archives/
icecast project homepage: http://www.icecast.org/
To unsubscribe from this list, send a message to 'icecast-dev-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the Icecast-dev mailing list