Example #1
0
File: net.cpp Project: ufoai/ufoai
static void do_accept (SOCKET sock)
{
	const int index = NET_StreamGetFree();
	if (index == -1) {
		Com_Printf("Too many streams open, rejecting inbound connection\n");
		netCloseSocket(sock);
		return;
	}

	struct net_stream* s = NET_StreamNew(index);
	s->socket = sock;
	s->inbound = dbufferptr(new dbuffer(4096));
	s->outbound = dbufferptr(new dbuffer(4096));
	s->family = server_family;
	s->addrlen = server_addrlen;
	s->func = server_func;

	maxfd = std::max(sock + 1, maxfd);
	FD_SET(sock, &read_fds);

	server_func(s);
	/** @todo close stream? */
}
Example #2
0
static struct net_stream* NET_DoConnect (const char* node, const char* service, const struct addrinfo* addr, int i, stream_onclose_func* onclose)
{
	struct net_stream* s;
	SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
	if (sock == INVALID_SOCKET) {
		Com_Printf("Failed to create socket: %s\n", netStringError(netError));
		return nullptr;
	}

	if (!NET_SocketSetNonBlocking(sock)) {
		netCloseSocket(sock);
		return nullptr;
	}

	if (connect(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
		const int err = netError;
#ifdef _WIN32
		if (err != WSAEWOULDBLOCK) {
#else
		if (err != EINPROGRESS) {
#endif
			Com_Printf("Failed to start connection to %s:%s: %s\n", node, service, netStringError(err));
			netCloseSocket(sock);
			return nullptr;
		}
	}

	s = NET_StreamNew(i);
	s->socket = sock;
	s->inbound = dbufferptr(new dbuffer(4096));
	s->outbound = dbufferptr(new dbuffer(4096));
	s->family = addr->ai_family;
	s->addrlen = addr->ai_addrlen;
	s->onclose = onclose;

	maxfd = std::max(sock + 1, maxfd);
	FD_SET(sock, &read_fds);

	return s;
}

/**
 * @brief Try to connect to a given host on a given port
 * @param[in] node The host to connect to
 * @param[in] service The port to connect to
 * @param[in] onclose The callback that is called on closing the returned stream. This is useful if
 * you hold the pointer for the returned stream anywhere else and would like to get notified once
 * this pointer is invalid.
 * @sa NET_DoConnect
 * @sa NET_ConnectToLoopBack
 * @todo What about a timeout
 */
struct net_stream* NET_Connect (const char* node, const char* service, stream_onclose_func* onclose)
{
	struct addrinfo* res;
	struct addrinfo hints;
	int rc;
	struct net_stream* s = nullptr;
	int index;

	OBJZERO(hints);
	hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
	hints.ai_socktype = SOCK_STREAM;
	/* force ipv4 */
	if (net_ipv4->integer)
		hints.ai_family = AF_INET;

	rc = getaddrinfo(node, service, &hints, &res);
	if (rc != 0) {
		Com_Printf("Failed to resolve host %s:%s: %s\n", node, service, gai_strerror(rc));
		return nullptr;
	}

	index = NET_StreamGetFree();
	if (index == -1) {
		Com_Printf("Failed to connect to host %s:%s, too many streams open\n", node, service);
		freeaddrinfo(res);
		return nullptr;
	}

	s = NET_DoConnect(node, service, res, index, onclose);

	freeaddrinfo(res);
	return s;
}

/**
 * @param[in] onclose The callback that is called on closing the returned stream. This is useful if
 * you hold the pointer for the returned stream anywhere else and would like to get notified once
 * this pointer is invalid.
 * @sa NET_Connect
 */
struct net_stream* NET_ConnectToLoopBack (stream_onclose_func* onclose)
{
	struct net_stream* client, *server;
	int server_index, client_index;

	if (!server_running)
		return nullptr;

	server_index = NET_StreamGetFree();
	client_index = NET_StreamGetFree();

	if (server_index == -1 || client_index == -1 || server_index == client_index) {
		Com_Printf("Failed to connect to loopback server, too many streams open\n");
		return nullptr;
	}

	client = NET_StreamNew(client_index);
	client->loopback = true;
	client->inbound = dbufferptr(new dbuffer(4096));
	client->outbound = dbufferptr(new dbuffer(4096));
	client->onclose = onclose;

	server = NET_StreamNew(server_index);
	server->loopback = true;
	server->inbound = client->outbound;
	server->outbound = client->inbound;
	server->func = server_func;
	server->onclose = nullptr;

	client->loopback_peer = server;
	server->loopback_peer = client;

	server_func(server);

	return client;
}

/**
 * @brief Enqueue a network message into a stream
 * @sa NET_StreamDequeue
 */
void NET_StreamEnqueue (struct net_stream* s, const char* data, int len)
{
	if (len <= 0 || !s || s->closed || s->finished)
		return;

	if (s->outbound) {
		const ScopedMutex scopedMutex(netMutex);
		s->outbound->add(data, len);
	}

	/* on linux, socket is int, and INVALID_SOCKET -1
	 * on windows it is unsigned and  INVALID_SOCKET (~0)
	 * Let's hope that checking for INVALID_SOCKET is good enough for linux. */
	//if (s->socket >= 0)
	if (s->socket != INVALID_SOCKET)
		FD_SET(s->socket, &write_fds);

	if (s->loopback_peer) {
		loopback_ready = true;
		s->loopback_peer->ready = true;
	}
}

/**
 * @brief Returns the length of the waiting inbound buffer
 */
static int NET_StreamPeek (struct net_stream* s, char* data, int len)
{
	if (len <= 0 || !s)
		return 0;

	dbufferptr& dbuf = s->inbound;
	if ((s->closed || s->finished) && dbuffer_len(dbuf) == 0)
		return 0;

	return dbuf->get(data, len);
}

/**
 * @sa NET_StreamEnqueue
 */
int NET_StreamDequeue (struct net_stream* s, char* data, int len)
{
	if (len <= 0 || !s || s->finished)
		return 0;

	return s->inbound->extract(data, len);
}

/**
 * @brief Reads messages from the network channel and adds them to the dbuffer
 * where you can use the NET_Read* functions to get the values in the correct
 * order
 * @sa NET_StreamDequeue
 */
dbuffer* NET_ReadMsg (struct net_stream* s)
{
	unsigned int v;
	const ScopedMutex scopedMutex(netMutex);

	if (NET_StreamPeek(s, (char*)&v, 4) < 4)
		return nullptr;

	int len = LittleLong(v);
	if (NET_StreamGetLength(s) < (4 + len))
		return nullptr;

	char tmp[256];
	const int size = sizeof(tmp);
	NET_StreamDequeue(s, tmp, 4);

	dbuffer* buf = new dbuffer();
	while (len > 0) {
		const int x = NET_StreamDequeue(s, tmp, std::min(len, size));
		buf->add(tmp, x);
		len -= x;
	}

	return buf;
}
int
main()
{
    gss_cred_id_t                       credential;
    int                                 listen_fd;
    int                                 accept_fd;
    struct sockaddr_un *                address;
    struct context_arg *                arg = NULL;
    pid_t                               pid;

    /* ToDo: Make this run on windows */
#   ifdef WIN32
    printf("This Test Doesn't Run On Windows Yet\n");
    exit(0);
#   endif

    /* module activation */

    globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE);
    globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE);
    globus_module_activate(GLOBUS_COMMON_MODULE);
    
    /* setup listener */

    address = malloc(sizeof(struct sockaddr_un));

    memset(address,0,sizeof(struct sockaddr_un));

    address->sun_family = PF_UNIX;

    tmpnam(address->sun_path);
    
    listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);

    bind(listen_fd, (struct sockaddr *) address, sizeof(struct sockaddr_un));

    listen(listen_fd,1);

    /* acquire credentials */

    credential = globus_gsi_gssapi_test_acquire_credential();

    if(credential == GSS_C_NO_CREDENTIAL)
    {
        fprintf(stderr,"Unable to aquire credential\n");
        exit(-1);
    }

    pid = fork();

    if(pid == 0)
    {
        /* child */
     	arg = malloc(sizeof(struct context_arg));
        
	arg->address = address;
        
	arg->credential = credential;

        client_func(arg);
    }
    else
    {
        accept_fd = accept(listen_fd,NULL,0);
        
	if(accept_fd < 0)
	{
	    abort();
	}
	
	arg = malloc(sizeof(struct context_arg));
        
	arg->fd = accept_fd;
        
	arg->credential = credential;

        server_func(arg);
    }

    /* close the listener */

    close(listen_fd);
    
    /* release credentials */
    
    globus_gsi_gssapi_test_release_credential(&credential); 
    
    /* free address */
    
    free(address);
    
    globus_module_deactivate(GLOBUS_COMMON_MODULE);
    globus_module_deactivate(GLOBUS_GSI_GSSAPI_MODULE);
    globus_module_deactivate(GLOBUS_GSI_GSS_ASSIST_MODULE);

    exit(0);
}