/*
* XmNap A Motif napster client
*
* Copyright (C) 2000 Mats Peterson
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any comments/bug reports to
*
[email protected] (Mats Peterson)
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include "main.h"
#include "connect.h"
#include "message.h"
#include "msgbox.h"
#include "netutil.h"
#include "util.h"
int MakeSocket(unsigned short int port, int *sock)
{
struct sockaddr_in name;
int status;
/* Create the socket. */
*sock = socket(PF_INET, SOCK_STREAM, 0);
if (*sock < 0)
return errno;
if (SetBlocked(*sock, 0))
goto error;
/* Give the socket a name. */
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
status = 1;
(void)setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, (char *) &status,
sizeof(status));
if (bind (*sock, (struct sockaddr*)&name, sizeof(name)) < 0)
goto error;
return 0;
error:
close(*sock);
return errno;
}
int InitSockAddr(struct sockaddr_in *name, const char *hostName,
unsigned short int port)
{
struct hostent *hostInfo;
name->sin_family = AF_INET;
name->sin_port = htons(port);
if (! (hostInfo = gethostbyname(hostName)))
return h_errno;
name->sin_addr = *(struct in_addr *) hostInfo->h_addr;
return 0;
}
int ConnSock(char *server, int port, int *sock)
{
struct sockaddr_in name;
time_t start;
int errVal = -1;
*sock = socket(PF_INET, SOCK_STREAM, 0);
if (*sock < 0) {
ErrMsg(strerror(errno));
return errVal;
}
if (SetBlocked(*sock, 0)) {
ErrMsg(strerror(errno));
goto error;
}
if (InitSockAddr(&name, server, port)) {
ErrMsg("Host name lookup failure");
goto error;
}
start = time(NULL);
while (0 > connect(*sock, (struct sockaddr *) &name, sizeof(name))) {
if ((errno != EINPROGRESS) && (errno != EALREADY)) {
if (errno == EISCONN)
break;
/* FreeBSD returns EINVAL instead of ECONNREFUSED */
if (errno == EINVAL)
errno = ECONNREFUSED;
#ifdef AUTORECONNECT_ON_REFUSED
if ((errno == ECONNREFUSED) && (sock == &srvSock)) {
ShowMiscInfo(strerror(errno), 0);
errVal = -2;
} else
#endif
ErrMsg(strerror(errno));
goto error;
}
if ((time(NULL) - start) >= timeOut) {
ErrMsg("Timeout");
goto error;
}
while (XtAppPending(appCon))
XtAppProcessEvent(appCon, XtIMAll);
usleep(1000);
}
return 0;
error:
close(*sock);
return errVal;
}
int WriteSock(char *data, int len)
{
int err, optLen = sizeof(int);
if (WriteChars(srvSock, data, len) == -1)
return -1;
if (getsockopt(srvSock, SOL_SOCKET, SO_ERROR,
(char*)&err, &optLen) == -1)
return -1;
if (err != 0) {
errno = err;
return -1;
}
return 0;
}
int SetBlocked(int fd, int blocked)
{
int oldState, curState;
if ((oldState = fcntl(fd, F_GETFL)) == -1)
return errno;
if (blocked)
curState = oldState & ~(O_NONBLOCK);
else
curState = oldState | O_NONBLOCK;
if (fcntl(fd, F_SETFL, curState) == -1)
return errno;
return 0;
}
void WaitVar(int *var, int timeout)
{
time_t t;
t = time(NULL);
while (*var == -1) {
if (XtAppPending(appCon))
XtAppProcessEvent(appCon, XtIMAll);
if ((time(NULL) - t) >= timeOut)
break;
usleep(1000);
}
}