Esempio n. 1
0
static void socketAccept(socket_t *sp)
{
	struct sockaddr_in	addr;
	socket_t 			*nsp;
	size_t				len;
	char				*pString;
	int 				newSock, nid;


#ifdef NW
	NETINET_DEFINE_CONTEXT;
#endif

	a_assert(sp);

/*
 *	Accept the connection and prevent inheriting by children (F_SETFD)
 */
	len = sizeof(struct sockaddr_in);
	if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, (int *) &len)) < 0) {
		return;
	}
#ifndef __NO_FCNTL
	fcntl(newSock, F_SETFD, FD_CLOEXEC);
#endif
	socketHighestFd = max(socketHighestFd, newSock);

/*
 *	Create a socket structure and insert into the socket list
 */
	nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags);
	nsp = socketList[nid];

	a_assert(nsp);
	if (nsp == NULL)
		return;

	nsp->sock = newSock;
	nsp->flags &= ~SOCKET_LISTENING;

/*
 *	Set the blocking mode before calling the accept callback.
 */

	socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0);
/*
 *	Call the user accept callback. The user must call socketCreateHandler
 *	to register for further events of interest.
 */
	if (sp->accept != NULL) {
		pString = inet_ntoa(addr.sin_addr);
		if ((sp->accept)(nid, pString, ntohs(addr.sin_port), sp->sid) < 0) {
			socketFree(nid);
		}
#ifdef VXWORKS
		free(pString);
#endif
	}
}
Esempio n. 2
0
/*
    Accept a connection. Called as a callback on incoming connection.
 */
static void socketAccept(WebsSocket *sp)
{
    struct sockaddr_storage addrStorage;
    struct sockaddr         *addr;
    WebsSocket              *nsp;
    Socket                  newSock;
    size_t                  len;
    char                    ipbuf[1024];
    int                     port, nid;

    assert(sp);

    /*
        Accept the connection and prevent inheriting by children (F_SETFD)
     */
    len = sizeof(addrStorage);
    addr = (struct sockaddr*) &addrStorage;
    if ((newSock = accept(sp->sock, addr, (Socklen*) &len)) == SOCKET_ERROR) {
        return;
    }
#if ME_COMPILER_HAS_FCNTL
    fcntl(newSock, F_SETFD, FD_CLOEXEC);
#endif
    socketHighestFd = max(socketHighestFd, newSock);

    /*
        Create a socket structure and insert into the socket list
     */
    nid = socketAlloc(sp->ip, sp->port, sp->accept, sp->flags);
    if ((nsp = socketList[nid]) == 0) {
        return;
    }
    assert(nsp);
    nsp->sock = newSock;
    nsp->flags &= ~SOCKET_LISTENING;
    socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK));
    if (nsp->flags & SOCKET_NODELAY) {
        socketSetNoDelay(nid, 1);
    }

    /*
        Call the user accept callback. The user must call socketCreateHandler to register for further events of interest.
     */
    if (sp->accept != NULL) {
        /* Get the remote client address */
        socketAddress(addr, (int) len, ipbuf, sizeof(ipbuf), &port);
        if ((sp->accept)(nid, ipbuf, port, sp->sid) < 0) {
            socketFree(nid);
        }
    }
}
Esempio n. 3
0
PUBLIC int socketConnect(char *ip, int port, int flags)
{
    WebsSocket                *sp;
    struct sockaddr_storage addr;
    socklen_t               addrlen;
    int                     family, protocol, sid, rc;

    if (port > SOCKET_PORT_MAX) {
        return -1;
    }
    if ((sid = socketAlloc(ip, port, NULL, flags)) < 0) {
        return -1;
    }
    sp = socketList[sid];
    assert(sp);

    if (socketInfo(ip, port, &family, &protocol, &addr, &addrlen) < 0) {
        return -1;       
    }
    if ((sp->sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) {
        socketFree(sid);
        return -1;
    }
    socketHighestFd = max(socketHighestFd, sp->sock);

#if ME_COMPILER_HAS_FCNTL
    fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
#endif

    /*
        Connect to the remote server in blocking mode, then go into non-blocking mode if desired.
     */
    if (!(sp->flags & SOCKET_BLOCK)) {
#if ME_WIN_LIKE
        /*
            Set to non-blocking for an async connect
         */
        int flag = 1;
        if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
            socketFree(sid);
            return -1;
        }
        sp->flags |= SOCKET_ASYNC;
#else
        socketSetBlock(sid, 1);
#endif
    }
    if ((rc = connect(sp->sock, (struct sockaddr*) &addr, sizeof(addr))) < 0 && 
        (rc = tryAlternateConnect(sp->sock, (struct sockaddr*) &addr)) < 0) {
#if ME_WIN_LIKE
        if (socketGetError() != EWOULDBLOCK) {
            socketFree(sid);
            return -1;
        }
#else
        socketFree(sid);
        return -1;

#endif
    }
    socketSetBlock(sid, (flags & SOCKET_BLOCK));
    return sid;
}
Esempio n. 4
0
PUBLIC int socketListen(char *ip, int port, SocketAccept accept, int flags)
{
    WebsSocket              *sp;
    struct sockaddr_storage addr;
    Socklen                 addrlen;
    char                    *sip;
    int                     family, protocol, sid, rc, only;

    if (port > SOCKET_PORT_MAX) {
        return -1;
    }
    if ((sid = socketAlloc(ip, port, accept, flags)) < 0) {
        return -1;
    }
    sp = socketList[sid];
    assert(sp);

    /*
        Change null IP address to be an IPv6 endpoint if the system is dual-stack. That way we can listen on
        both IPv4 and IPv6
    */
    sip = ((ip == 0 || *ip == '\0') && socketHasDualNetworkStack()) ? "::" : ip;

    /*
        Bind to the socket endpoint and the call listen() to start listening
     */
    if (socketInfo(sip, port, &family, &protocol, &addr, &addrlen) < 0) {
        return -1;
    }
    if ((sp->sock = socket(family, SOCK_STREAM, protocol)) == SOCKET_ERROR) {
        socketFree(sid);
        return -1;
    }
    socketHighestFd = max(socketHighestFd, sp->sock);

#if ME_COMPILER_HAS_FCNTL
    fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
#endif
    rc = 1;
#if ME_UNIX_LIKE || VXWORKS
    setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char*) &rc, sizeof(rc));
#elif ME_WIN_LIKE && defined(SO_EXCLUSIVEADDRUSE)
    setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR | SO_EXCLUSIVEADDRUSE, (char*) &rc, sizeof(rc));
#endif

#if defined(IPV6_V6ONLY)
    /*
        By default, most stacks listen on both IPv6 and IPv4 if ip == 0, except windows which inverts this.
        So we explicitly control.
     */
    if (hasIPv6) {
        if (ip == 0) {
            only = 0;
            setsockopt(sp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &only, sizeof(only));
        } else if (ipv6(ip)) {
            only = 1;
            setsockopt(sp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &only, sizeof(only));
        }
    }
#endif
    if (bind(sp->sock, (struct sockaddr*) &addr, addrlen) == SOCKET_ERROR) {
        error("Can't bind to address %s:%d, errno %d", ip ? ip : "*", port, errno);
        socketFree(sid);
        return -1;
    }
    if (listen(sp->sock, SOMAXCONN) < 0) {
        socketFree(sid);
        return -1;
    }
    sp->flags |= SOCKET_LISTENING | SOCKET_NODELAY;
    sp->handlerMask |= SOCKET_READABLE;
    socketSetBlock(sid, (flags & SOCKET_BLOCK));
    if (sp->flags & SOCKET_NODELAY) {
        socketSetNoDelay(sid, 1);
    }
    return sid;
}
Esempio n. 5
0
int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags)
{
#if (!defined (NO_GETHOSTBYNAME) && !defined (VXWORKS))
	struct hostent		*hostent;					/* Host database entry */
#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */
	socket_t			*sp;
	struct sockaddr_in	sockaddr;
	int					sid, bcast, dgram, rc;
#ifdef WF_USE_IPV6
	int					gaierr;
	char				portstr[10];
	struct addrinfo		hints;
	struct addrinfo		*ai, *ai2, *aiv6 = NULL;
	struct sockaddr_in6	sockaddr6;
#endif

	if (port > SOCKET_PORT_MAX) {
		return -1;
	}
/*
 *	Allocate a socket structure
 */
	if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
		return -1;
	}
	sp = socketList[sid];
	a_assert(sp);

/*
 *	Create the socket address structure
 */
#ifdef WF_USE_IPV6
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_flags = AI_PASSIVE;
	hints.ai_socktype = SOCK_STREAM;

	snprintf(portstr, sizeof(portstr), "%d", port);
	if ((gaierr = getaddrinfo(host, portstr, &hints, &ai)) != 0) {
		fprintf(stderr, "goahead: getaddrinfo - %s\n", gai_strerror(gaierr));
		socketFree(sid);
		return -1;
	}
	aiv6 = NULL;
	for (ai2 = ai; ai2 != (struct addrinfo*)0; ai2 = ai2->ai_next) {
		switch (ai2->ai_family) {
			case AF_INET6:
				if (aiv6 == NULL)
					aiv6 = ai2;
				break;
		}
	}
	if (aiv6 == NULL) {
		fprintf(stderr, "goahead: cannot find IPv6 addrinfo\n");
		socketFree(sid);
		return -1;
	}
	memcpy(&sockaddr6, aiv6->ai_addr, aiv6->ai_addrlen);
	freeaddrinfo(ai);
#else /* WF_USE_IPV6 */
	memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons((short) (port & 0xFFFF));

	if (host == NULL) {
		sockaddr.sin_addr.s_addr = INADDR_ANY;
	} else {
		sockaddr.sin_addr.s_addr = inet_addr(host);
		if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
/*
 *			If the OS does not support gethostbyname functionality, the macro:
 *			NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname.
 *			Unfortunatly there is no easy way to recover, the following code
 *			simply uses the basicGetHost IP for the sockaddr.
 */

#ifdef NO_GETHOSTBYNAME
			if (strcmp(host, basicGetHost()) == 0) {
				sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress());
			}
			if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
				socketFree(sid);
				return -1;
			}
#elif (defined (VXWORKS))
			sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host);
			if (sockaddr.sin_addr.s_addr == NULL) {
				errno = ENXIO;
				socketFree(sid);
				return -1;
			}
#else
			hostent = gethostbyname(host);
			if (hostent != NULL) {
				memcpy((char *) &sockaddr.sin_addr, 
					(char *) hostent->h_addr_list[0],
					(size_t) hostent->h_length);
			} else {
				char	*asciiAddress;
				char_t	*address;

				address = basicGetAddress();
				asciiAddress = ballocUniToAsc(address, gstrlen(address));
				sockaddr.sin_addr.s_addr = inet_addr(asciiAddress);
				bfree(B_L, asciiAddress);
				if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
					errno = ENXIO;
					socketFree(sid);
					return -1;
				}
			}
#endif /* (NO_GETHOSTBYNAME || VXWORKS) */
		}
	}
#endif /* WF_USE_IPV6 */

	bcast = sp->flags & SOCKET_BROADCAST;
	if (bcast) {
		sp->flags |= SOCKET_DATAGRAM;
	}
	dgram = sp->flags & SOCKET_DATAGRAM;

/*
 *	Create the socket. Support for datagram sockets. Set the close on
 *	exec flag so children don't inherit the socket.
 */
#ifdef WF_USE_IPV6
	sp->sock = socket(AF_INET6, SOCK_STREAM, 0);
#else
	sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
#endif
	if (sp->sock < 0) {
		socketFree(sid);
		return -1;
	}
#ifndef __NO_FCNTL
	fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
#endif
	socketHighestFd = max(socketHighestFd, sp->sock);

/*
 *	If broadcast, we need to turn on broadcast capability.
 */
	if (bcast) {
		int broadcastFlag = 1;
		if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST,
				(char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) {
			socketFree(sid);
			return -1;
		}
	}

/*
 *	Host is set if we are the client
 */
	if (host) {
/*
 *		Connect to the remote server in blocking mode, then go into 
 *		non-blocking mode if desired.
 */
		if (!dgram) {
			if (! (sp->flags & SOCKET_BLOCK)) {
/*
 *				sockGen.c is only used for Windows products when blocking
 *				connects are expected.  This applies to FieldUpgrader
 *				agents and open source webserver connectws.  Therefore the
 *				asynchronous connect code here is not compiled.
 */
#if (defined (WIN) || defined (CE)) && (!defined (LITTLEFOOT) && !defined (WEBS))
				int flag;

				sp->flags |= SOCKET_ASYNC;
/*
 *				Set to non-blocking for an async connect
 */
				flag = 1;
				if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
					socketFree(sid);
					return -1;
				}
#else
				socketSetBlock(sid, 1);
#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */

			}
			if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr,
				sizeof(sockaddr))) < 0 && 
				(rc = tryAlternateConnect(sp->sock,
				(struct sockaddr *) &sockaddr)) < 0) {
#if (defined (WIN) || defined (CE))
				if (socketGetError() != EWOULDBLOCK) {
					socketFree(sid);
					return -1;
				}
#else
				socketFree(sid);
				return -1;

#endif /* WIN || CE */

			}
		}
	} else {
/*
 *		Bind to the socket endpoint and the call listen() to start listening
 */
		rc = 1;
		setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
#ifdef WF_USE_IPV6
		if (bind(sp->sock, (struct sockaddr *) &sockaddr6,
				sizeof(sockaddr6)) < 0) {
#else
		if (bind(sp->sock, (struct sockaddr *) &sockaddr, 
				sizeof(sockaddr)) < 0) {
#endif
			socketFree(sid);
			return -1;
		}

		if (! dgram) {
			if (listen(sp->sock, SOMAXCONN) < 0) {
				socketFree(sid);
				return -1;
			}
			sp->flags |= SOCKET_LISTENING;
		}
		sp->handlerMask |= SOCKET_READABLE;
	}

/*
 *	Set the blocking mode
 */

	if (flags & SOCKET_BLOCK) {
		socketSetBlock(sid, 1);
	} else {
		socketSetBlock(sid, 0);
	}
	return sid;
}


/******************************************************************************/
/*
 *	If the connection failed, swap the first two bytes in the 
 *	sockaddr structure.  This is a kludge due to a change in
 *	VxWorks between versions 5.3 and 5.4, but we want the 
 *	product to run on either.
 */

static int tryAlternateConnect(int sock, struct sockaddr *sockaddr)
{
#ifdef VXWORKS
	char *ptr;

	ptr = (char *)sockaddr;
	*ptr = *(ptr+1);
	*(ptr+1) = 0;
	return connect(sock, sockaddr, sizeof(struct sockaddr));
#else
	return -1;
#endif /* VXWORKS */
}
Esempio n. 6
0
int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags)
{
#if (!defined (NO_GETHOSTBYNAME) && !defined (VXWORKS))
	struct hostent		*hostent;					/* Host database entry */
#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */
	socket_t			*sp;
	struct sockaddr_in	sockaddr;
	int					sid, bcast, dgram, rc;

	if (port > SOCKET_PORT_MAX) {
		return -1;
	}
/*
 *	Allocate a socket structure
 */
	if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
		return -1;
	}
	sp = socketList[sid];
	a_assert(sp);

/*
 *	Create the socket address structure
 */
	memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons((short) (port & 0xFFFF));

	if (host == NULL) {
		sockaddr.sin_addr.s_addr = INADDR_ANY;
	} else {
		sockaddr.sin_addr.s_addr = inet_addr(host);
		if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
/*
 *			If the OS does not support gethostbyname functionality, the macro:
 *			NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname.
 *			Unfortunatly there is no easy way to recover, the following code
 *			simply uses the basicGetHost IP for the sockaddr.
 */

#ifdef NO_GETHOSTBYNAME
			if (strcmp(host, basicGetHost()) == 0) {
				sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress());
			}
			if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
				socketFree(sid);
				return -1;
			}
#elif (defined (VXWORKS))
			sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host);
			if (sockaddr.sin_addr.s_addr == NULL) {
				errno = ENXIO;
				socketFree(sid);
				return -1;
			}
#else
			hostent = gethostbyname(host);
			if (hostent != NULL) {
				memcpy((char *) &sockaddr.sin_addr, 
					(char *) hostent->h_addr_list[0],
					(size_t) hostent->h_length);
			} else {
				char	*asciiAddress;
				char	*address;

				address = basicGetAddress();
				asciiAddress = ballocUniToAsc(address, gstrlen(address));
				sockaddr.sin_addr.s_addr = inet_addr(asciiAddress);
				bfree(B_L, asciiAddress);
				if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
					errno = ENXIO;
					socketFree(sid);
					return -1;
				}
			}
#endif /* (NO_GETHOSTBYNAME || VXWORKS) */
		}
	}

	bcast = sp->flags & SOCKET_BROADCAST;
	if (bcast) {
		sp->flags |= SOCKET_DATAGRAM;
	}
	dgram = sp->flags & SOCKET_DATAGRAM;

/*
 *	Create the socket. Support for datagram sockets. Set the close on
 *	exec flag so children don't inherit the socket.
 */
	sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
	if (sp->sock < 0) {
		socketFree(sid);
		return -1;
	}
#ifndef __NO_FCNTL
	fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
#endif
	socketHighestFd = max(socketHighestFd, sp->sock);

/*
 *	If broadcast, we need to turn on broadcast capability.
 */
	if (bcast) {
		int broadcastFlag = 1;
		if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST,
				(char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) {
			socketFree(sid);
			return -1;
		}
	}

/*
 *	Host is set if we are the client
 */
	if (host) {
/*
 *		Connect to the remote server in blocking mode, then go into 
 *		non-blocking mode if desired.
 */
		if (!dgram) {
			if (! (sp->flags & SOCKET_BLOCK)) {
/*
 *				sockGen.c is only used for Windows products when blocking
 *				connects are expected.  This applies to FieldUpgrader
 *				agents and open source webserver connectws.  Therefore the
 *				asynchronous connect code here is not compiled.
 */
#if (defined (WIN) || defined (CE)) && (!defined (LITTLEFOOT) && !defined (WEBS))
				int flag;

				sp->flags |= SOCKET_ASYNC;
/*
 *				Set to non-blocking for an async connect
 */
				flag = 1;
				if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
					socketFree(sid);
					return -1;
				}
#else
				socketSetBlock(sid, 1);
#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */

			}
			if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr,
				sizeof(sockaddr))) < 0 && 
				(rc = tryAlternateConnect(sp->sock,
				(struct sockaddr *) &sockaddr)) < 0) {
#if (defined (WIN) || defined (CE))
				if (socketGetError() != EWOULDBLOCK) {
					socketFree(sid);
					return -1;
				}
#else
				socketFree(sid);
				return -1;

#endif /* WIN || CE */

			}
		}
	} else {
/*
 *		Bind to the socket endpoint and the call listen() to start listening
 */
		rc = 1;
		setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
		if (bind(sp->sock, (struct sockaddr *) &sockaddr, 
				sizeof(sockaddr)) < 0) {
			socketFree(sid);
			return -1;
		}

		if (! dgram) {
			if (listen(sp->sock, SOMAXCONN) < 0) {
				socketFree(sid);
				return -1;
			}
#ifndef UEMF
			sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE,
				(emfFileProc *) socketAccept, (void *) sp);
#else
			sp->flags |= SOCKET_LISTENING;
#endif
		}
		sp->handlerMask |= SOCKET_READABLE;
	}

/*
 *	Set the blocking mode
 */

	if (flags & SOCKET_BLOCK) {
		socketSetBlock(sid, 1);
	} else {
		socketSetBlock(sid, 0);
	}
	return sid;
}