Exemple #1
0
static void socketDoEvent(WebsSocket *sp)
{
    int     sid;

    assert(sp);

    sid = sp->sid;
    if (sp->currentEvents & SOCKET_READABLE) {
        if (sp->flags & SOCKET_LISTENING) { 
            socketAccept(sp);
            sp->currentEvents = 0;
            return;
        } 
    }
    /*
        Now invoke the users socket handler. NOTE: the handler may delete the
        socket, so we must be very careful after calling the handler.
     */
    if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
        (sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data);
        /*
            Make sure socket pointer is still valid, then reset the currentEvents.
         */ 
        if (socketList && sid < socketMax && socketList[sid] == sp) {
            sp->currentEvents = 0;
        }
    }
}
int socketCreatePair(int* fd1, int* fd2) {
#ifndef _WIN32
    int fds[2];
    int ret = ::socketpair(AF_UNIX, SOCK_STREAM, 0, fds);

    if (!ret) {
        socketSetNonBlocking(fds[0]);
        socketSetNonBlocking(fds[1]);
        *fd1 = fds[0];
        *fd2 = fds[1];
    } else {
        DPLOG(ERROR) << "Could not create socket pair\n";
    }
    return ret;
#else /* _WIN32 */
    /* on Windows, select() only works with network sockets, which
     * means we absolutely cannot use Win32 PIPEs to implement
     * socket pairs with the current event loop implementation.
     * We're going to do like Cygwin: create a random pair
     * of localhost TCP sockets and connect them together
     */

    /* first, create the 'server' socket.
     * a port number of 0 means 'any port between 1024 and 5000.
     * see Winsock bind() documentation for details */
    ScopedSocket s0(socketTcpLoopbackServer(0));
    if (s0.get() < 0) {
        return -1;
    }

    // IMPORTANT: Keep the s0 socket in blocking mode, or the accept()
    // below may fail with WSAEWOULDBLOCK randomly.

    /* now connect a client socket to it, we first need to
     * extract the server socket's port number */
    int port = socketGetPort(s0.get());

    ScopedSocket s2(socketTcpLoopbackClient(port));
    if (!s2.valid()) {
        return -1;
    }

    /* we need to accept the connection on the server socket
     * this will create the second socket for the pair
     */
    ScopedSocket s1(socketAccept(s0.get()));
    if (!s1.valid()) {
        DPLOG(ERROR) << "Could not accept connection from server socket\n";
        return -1;
    }
    socketSetNonBlocking(s1.get());

    *fd1 = s1.release();
    *fd2 = s2.release();

    return 0;
#endif /* _WIN32 */
}
static int socketDoEvent(socket_t *sp)
{
	ringq_t		*rq;
	int 		sid;

	a_assert(sp);

	sid = sp->sid;
	if (sp->currentEvents & SOCKET_READABLE) {
		if (sp->flags & SOCKET_LISTENING) { 
			socketAccept(sp);
			sp->currentEvents = 0;
			return 1;
		} 

	} else {
/*
 *		If there is still read data in the buffers, trigger the read handler
 *		NOTE: this may busy spin if the read handler doesn't read the data
 */
		if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
			sp->currentEvents |= SOCKET_READABLE;
		}
	}


/*
 *	If now writable and flushing in the background, continue flushing
 */
	if (sp->currentEvents & SOCKET_WRITABLE) {
		if (sp->flags & SOCKET_FLUSHING) {
			rq = &sp->outBuf;
			if (ringqLen(rq) > 0) {
				socketFlush(sp->sid);
			} else {
				sp->flags &= ~SOCKET_FLUSHING;
			}
		}
	}

/*
 *	Now invoke the users socket handler. NOTE: the handler may delete the
 *	socket, so we must be very careful after calling the handler.
 */
	if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
		(sp->handler)(sid, sp->handlerMask & sp->currentEvents, 
			sp->handler_data);
/*
 *		Make sure socket pointer is still valid, then reset the currentEvents.
 */ 
		if (socketList && sid < socketMax && socketList[sid] == sp) {
			sp->currentEvents = 0;
		}
	}
	return 1;
}
Exemple #4
0
static void scanSockets(void)
{
	uint16 i;

	for (i = 0; i < SOAD_SOCKET_COUNT; i++) {
//		pi_printf("infor: scan sockets "); mini_uart_sendDec(i); pi_printf(" \r\n");
		switch (SocketAdminList[i].SocketState) {
		case SOCKET_INIT:

			socketCreate(i);
//			pi_printf("infor: socket create"); mini_uart_sendDec(i); pi_printf(" \r\n");
			break;

		case SOCKET_TCP_LISTENING:
			socketAccept(i);
//			pi_printf("infor: socket accept"); mini_uart_sendDec(i); pi_printf(" \r\n");
			break;

		case SOCKET_TCP_READY:

//			pi_printf("infor: socket read "); mini_uart_sendDec(i); pi_printf(" \r\n");
			socketTcpRead(i);
			break;

		case SOCKET_UDP_READY:
			socketUdpRead(i);
			break;

		case SOCKET_DUPLICATE:
			/* Do nothing */
			break;

		default:
			/* This should never happen! */
			DET_REPORTERROR(MODULE_ID_SOAD, 0, SOAD_SCAN_SOCKETS_ID, SOAD_E_SHALL_NOT_HAPPEN);
			break;
		} /* End of switch */
	} /* End of for */


}
Exemple #5
0
void CSocketServer::runSocketAccept()
{
	int nChildSocketFD = -1;

	while (1)
	{
		nChildSocketFD = socketAccept();

		if (-1 != nChildSocketFD)
		{
			sendMessage(m_nInternalFilter, EVENT_COMMAND_SOCKET_ACCEPT, nChildSocketFD, 0, NULL);
		}
		else
		{
			_DBG("socket server accept fail");
			sleep(3);
		}
	}

	sendMessage(m_nInternalFilter, EVENT_COMMAND_THREAD_EXIT, threadHandler->getThreadID(), 0, NULL);
	threadHandler->threadExit();
}
Exemple #6
0
void CHttpServer::runSocketAccept()
{
	int nChildSocketFD = -1;

	while (1)
	{
		nChildSocketFD = socketAccept();

		if (-1 != nChildSocketFD)
		{
			sendMessage(EVENT_FILTER_HTTP_SERVER, EVENT_COMMAND_SOCKET_ACCEPT,
					nChildSocketFD, 0, NULL);
		}
		else
		{
			_DBG("socket server accept fail");
		}
	}

	sendMessage(EVENT_FILTER_HTTP_SERVER, EVENT_COMMAND_THREAD_EXIT,
			threadHandler->getThreadID(), 0, NULL);
	threadHandler->threadExit();
}
Exemple #7
0
void tcpEchoListenerTask(void *param)
{
   error_t error;
   uint16_t clientPort;
   IpAddr clientIpAddr;
   Socket *serverSocket;
   Socket *clientSocket;
   EchoServiceContext *context;
   OsTask *task;

   //Point to the listening socket
   serverSocket = (Socket *) param;

   //Main loop
   while(1)
   {
      //Accept an incoming connection
      clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort);
      //Check whether a valid connection request has been received
      if(!clientSocket) continue;

      //Debug message
      TRACE_INFO("Echo service: connection established with client %s port %u\r\n",
         ipAddrToString(&clientIpAddr, NULL), clientPort);

      //The socket operates in non-blocking mode
      error = socketSetTimeout(clientSocket, 0);

      //Any error to report?
      if(error)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Allocate resources for the new connection
      context = osMemAlloc(sizeof(EchoServiceContext));

      //Failed to allocate memory?
      if(!context)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Record the handle of the newly created socket
      context->socket = clientSocket;

      //Create a task to service the current connection
      task = osTaskCreate("TCP Echo Connection", tcpEchoConnectionTask,
         context, ECHO_SERVICE_STACK_SIZE, ECHO_SERVICE_PRIORITY);

      //Did we encounter an error?
      if(task == OS_INVALID_HANDLE)
      {
         //Close socket
         socketClose(clientSocket);
         //Release resources
         osMemFree(context);
      }
   }
}
Exemple #8
0
int_t accept(int_t s, sockaddr *addr, int_t *addrlen)
{
   uint16_t port;
   IpAddr ipAddr;
   Socket *socket;
   Socket *newSocket;

   //Make sure the socket descriptor is valid
   if(s < 0 || s >= SOCKET_MAX_COUNT)
   {
      socketError(NULL, ERROR_INVALID_SOCKET);
      return SOCKET_ERROR;
   }

   //Point to the socket structure
   socket = &socketTable[s];

   //Permit an incoming connection attempt on a socket
   newSocket = socketAccept(socket, &ipAddr, &port);

   //The address is optional
   if(addr != NULL && addrlen != NULL)
   {
#if (IPV4_SUPPORT == ENABLED)
      //IPv4 address?
      if(ipAddr.length == sizeof(Ipv4Addr) && *addrlen >= sizeof(sockaddr_in))
      {
         //Point to the IPv4 address information
         sockaddr_in *sa = (sockaddr_in *) addr;

         //Set address family and port number
         sa->sin_family = AF_INET;
         sa->sin_port = htons(port);
         //Copy IPv4 address
         sa->sin_addr.s_addr = ipAddr.ipv4Addr;

         //Return the actual length of the address
         *addrlen = sizeof(sockaddr_in);
      }
      else
#endif
#if (IPV6_SUPPORT == ENABLED)
      //IPv6 address?
      if(ipAddr.length == sizeof(Ipv6Addr) && *addrlen >= sizeof(sockaddr_in6))
      {
         //Point to the IPv6 address information
         sockaddr_in6 *sa = (sockaddr_in6 *) addr;

         //Set address family and port number
         sa->sin6_family = AF_INET6;
         sa->sin6_port = htons(port);
         //Copy IPv6 address
         ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);

         //Return the actual length of the address
         *addrlen = sizeof(sockaddr_in6);
      }
      else
#endif
      //Invalid address?
      {
         //Close socket
         socketClose(newSocket);
         //Report an error
         socketError(socket, ERROR_INVALID_PARAMETER);
         return SOCKET_ERROR;
      }
   }

   //Return the descriptor to the new socket
   return newSocket->descriptor;
}
Exemple #9
0
int main(int argc, char **argv)
#endif
{
	sslConn_t		*cp;
	sslKeys_t		*keys;
	SOCKET			listenfd, fd;
	WSADATA			wsaData;
	unsigned char	buf[1024];
	unsigned char	*response, *c;
	int				responseHdrLen, acceptAgain, flags;
	int				bytes, status, quit, again, rc, err;
#if USE_MEM_CERTS
	unsigned char	*servBin, *servKeyBin, *caBin; 
	int				servBinLen, caBinLen, servKeyBinLen;
#endif

	cp = NULL;
/*
	Initialize Windows sockets (no-op on other platforms)
*/
	WSAStartup(MAKEWORD(1,1), &wsaData);
/*
	Initialize the MatrixSSL Library, and read in the public key (certificate)
	and private key.
*/
	if (matrixSslOpen() < 0) {
		fprintf(stderr, "matrixSslOpen failed, exiting...");
	}

#if USE_MEM_CERTS
/*
	Example of DER binary certs for matrixSslReadKeysMem
*/
	getFileBin("certSrv.der", &servBin, &servBinLen);
	getFileBin("privkeySrv.der", &servKeyBin, &servKeyBinLen);
	getFileBin("CACertCln.der", &caBin, &caBinLen);

	matrixSslReadKeysMem(&keys, servBin, servBinLen,
		servKeyBin, servKeyBinLen, caBin, caBinLen); 

	free(servBin);
	free(servKeyBin);
	free(caBin);
#else 
/*
	Standard PEM files
*/
	if (matrixSslReadKeys(&keys, certfile, keyfile, NULL, NULL) < 0)  {
		fprintf(stderr, "Error reading or parsing %s or %s.\n", 
			certfile, keyfile);
		goto promptAndExit;
	}
#endif /* USE_MEM_CERTS */
	fprintf(stdout, 
		"Run httpsClient or type https://127.0.0.1:%d into your local Web browser.\n",
		HTTPS_PORT);
/*
	Create the listen socket
*/
	if ((listenfd = socketListen(HTTPS_PORT, &err)) == INVALID_SOCKET) {
		fprintf(stderr, "Cannot listen on port %d\n", HTTPS_PORT);
		goto promptAndExit;
	}
/*
	Set blocking or not on the listen socket
*/
	setSocketBlock(listenfd);
/*
	Loop control initalization
*/
	quit = 0;
	again = 0;
	flags = 0;

	acceptAgain = 1;
/*
	Main connection loop
*/
	while (!quit) {

		if (acceptAgain) {
/*
			sslAccept creates a new server session
*/
			/* TODO - deadlock on blocking socket accept.  Should disable blocking here */
			if ((fd = socketAccept(listenfd, &err)) == INVALID_SOCKET) {
				fprintf(stdout, "Error accepting connection: %d\n", err);
				continue;
			}
			if ((rc = sslAccept(&cp, fd, keys, NULL, flags)) != 0) {
				socketShutdown(fd);
				continue;
			}

			flags = 0;
			acceptAgain = 0;
		}
/*
		Read response
		< 0 return indicates an error.
		0 return indicates an EOF or CLOSE_NOTIFY in this situation
		> 0 indicates that some bytes were read.  Keep reading until we see
		the /r/n/r/n from the GET request.  We don't actually parse the request,
		we just echo it back.
*/
		c = buf;
readMore:
		if ((rc = sslRead(cp, c, sizeof(buf) - (int)(c - buf), &status)) > 0) {
			c += rc;
			if (c - buf < 4 || memcmp(c - 4, "\r\n\r\n", 4) != 0) {
				goto readMore;
			}
		} else {
			if (rc < 0) {
				fprintf(stdout, "sslRead error.  dropping connection.\n");
			}
			if (rc < 0 || status == SSLSOCKET_EOF ||
					status == SSLSOCKET_CLOSE_NOTIFY) {
				socketShutdown(cp->fd);
				sslFreeConnection(&cp);
				acceptAgain = 1;
				continue;
			}
			goto readMore;
		}
/*
		Done reading.  If the incoming data starts with the quitString,
		quit the application after this request
*/
		if (memcmp(buf, quitString, min(c - buf, 
				(int)strlen(quitString))) == 0) {
			quit++;
			fprintf(stdout, "Q");
		}
/*
		If the incoming data starts with the againString,
		we are getting a pipeline request on the same session.  Don't
		close and wait for new connection in this case.
*/
		if (memcmp(buf, againString,
				min(c - buf, (int)strlen(againString))) == 0) {
			again++;
			fprintf(stdout, "A");
		} else {
			fprintf(stdout, "R");
			again = 0;
		}
/*
		Copy the canned response header and decoded data from socket as the
		response (reflector)
*/
		responseHdrLen = (int)strlen(responseHdr);
		bytes = responseHdrLen + (int)(c - buf);
		response = malloc(bytes);
		memcpy(response, responseHdr, responseHdrLen);
		memcpy(response + responseHdrLen, buf, c - buf); 
/*
		Send response.
		< 0 return indicates an error.
		0 return indicates not all data was sent and we must retry
		> 0 indicates that all requested bytes were sent
*/
writeMore:
		rc = sslWrite(cp, response, bytes, &status);
		if (rc < 0) {
			free(response);
			fprintf(stdout, "Internal sslWrite error\n");
			socketShutdown(cp->fd);
			sslFreeConnection(&cp);
			continue;
		} else if (rc == 0) {
			goto writeMore;
		}
		free(response);
/*
		If we saw an /again request, loop up and process another pipelined
		HTTP request.  The /again request is supported in the httpsClient
		example code.
*/
		if (again) {
			continue;
		}
/*
		Send a closure alert for clean shutdown of remote SSL connection
		This is for good form, some implementations just close the socket
*/
		sslWriteClosureAlert(cp);
/*
		Close the socket and wait for next connection (new session)
*/
		socketShutdown(cp->fd);
		sslFreeConnection(&cp);
		acceptAgain = 1;
	}
/*
	Close listening socket, free remaining items
*/
	if (cp && cp->ssl) {
		socketShutdown(cp->fd);
		sslFreeConnection(&cp);
	}
	socketShutdown(listenfd);

	matrixSslFreeKeys(keys);
	matrixSslClose();
	WSACleanup();
promptAndExit:
	fprintf(stdout, "\n\nPress return to exit...\n");
	getchar();
	return 0;
}
Exemple #10
0
API bool connectClientSocketAsync(Socket *s, int timeout)
{
	if(s->connected) {
		logError("Cannot connect already connected socket %d", s->fd);
		return false;
	}

	if(s->type != SOCKET_CLIENT) {
		logError("Cannot asynchronously connect non-client socket");
		return false;
	}

	struct addrinfo hints;
	struct addrinfo *server;
	int ret;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC; // don't care if we use IPv4 or IPv6 to reach our destination
	hints.ai_socktype = SOCK_STREAM; // TCP stream sockets

	if((ret = getaddrinfo(s->host, s->port, &hints, &server)) != 0) {
		logError("Failed to look up address %s:%s: %s", s->host, s->port, gai_strerror(ret));
		return false;
	}

	if((s->fd = socket(server->ai_family, server->ai_socktype, server->ai_protocol)) == -1) {
		logSystemError("Failed to create socket");
		return false;
	}

	if(!setSocketNonBlocking(s->fd)) {
		logSystemError("Failed to set socket non-blocking");
		closeSocket(s);
		return false;
	}

	logNotice("Asynchronously connecting client socket %d to %s:%s...", s->fd, s->host, s->port);

	if(connect(s->fd, server->ai_addr, server->ai_addrlen) < 0) { // try to connect socket
#ifdef WIN32
		if(WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK) {
#else
		if(errno == EINPROGRESS) {
#endif
			// free previous timer if present
			free(s->custom);

			AsyncConnectionTimer *timer = ALLOCATE_OBJECT(AsyncConnectionTimer);
			timer->creationTime = getMicroTime();
			timer->timeout = timeout;
			s->custom = timer;

			g_queue_push_tail(connecting, s); // add to connecting list
			logInfo("Socket %d delayed connection, queueing...", s->fd);
		} else {
#ifdef WIN32
			char *error = g_win32_error_message(WSAGetLastError());
			logError("Connection for socket %d failed: %s", s->fd, error);
			free(error);
#else
			logSystemError("Connection for socket %d failed", s->fd);
#endif
			closeSocket(s);
			freeaddrinfo(server);
			return false;
		}
	} else {
		logNotice("Direct response for asynchronous connection on socket %d", s->fd);
		s->connected = true;
		triggerEvent(s, "connected");
		enableSocketPolling(s);
	}

	freeaddrinfo(server);
	return true;
}

API bool enableSocketPolling(Socket *socket)
{
	if(isSocketPollingEnabled(socket)) { // Socket with that fd is already polled
		return false;
	}

	int *fd = ALLOCATE_OBJECT(int);
	*fd = socket->fd;

	g_hash_table_insert(poll_table, fd, socket);
	return true;
}

API bool isSocketPollingEnabled(Socket *socket)
{
	return g_hash_table_lookup(poll_table, &socket->fd) != NULL;
}

API bool disableSocketPolling(Socket *socket)
{
	return g_hash_table_remove(poll_table, &socket->fd) == true;
}

API void pollSockets()
{
	if(!polling) {
		polling = true; // set polling flag to lock our poll table in order to make this function reentrancy safe

		if(!g_queue_is_empty(connecting)) {
			GQueue *connectingSockets = g_queue_copy(connecting); // copy the connecting socket list so we may modify the list while polling
			for(GList *iter = connectingSockets->head; iter != NULL; iter = iter->next) {
				if(pollConnectingSocket(iter->data)) { // poll the connecting socket
					// The socket should no longer be polled
					g_queue_remove(connecting, iter->data); // remove it from the original connecting queue
				}
			}
			g_queue_free(connectingSockets); // remove our temporary iteration list
		}

		GList *sockets = g_hash_table_get_values(poll_table); // get a static list of sockets so we may modify the hash table while polling
		for(GList *iter = sockets; iter != NULL; iter = iter->next) {
			Socket *poll = iter->data;
			int fd; // storage for the file descriptor that won't be available anymore in case the socket gets freed before we remove it
			if(pollSocket(poll, &fd)) { // poll the socket
				// The socket should no longer be polled
				g_hash_table_remove(poll_table, &fd); // remove it from the polling table
			}
		}
		g_list_free(sockets); // remove our temporary iteration list
		polling = false; // release pseudo lock on poll table
	}
}

API bool isSocketsPolling()
{
	return polling;
}

API Socket *getPolledSocketByFd(int fd)
{
	return g_hash_table_lookup(poll_table, &fd);
}

/**
 * Callback to poll all sockets signed up for polling
 */
TIMER_CALLBACK(poll)
{
	pollSockets();
	triggerEvent(NULL, "sockets_polled");
	TIMER_ADD_TIMEOUT(pollInterval, poll);
}

/**
 * Polls a connecting socket and notifies the caller of whether it should be removed from the connecting polling queue afterwards
 *
 * @param socket		the connecting socket to poll
 * @result				true if the socket should be removed from the connecting polling queue after polling
 */
static bool pollConnectingSocket(Socket *socket)
{
	assert(!socket->connected);
	assert(socket->type == SOCKET_CLIENT);
	assert(socket->custom != NULL);

	// Check whether the socket has timed out yet
	AsyncConnectionTimer *timer = socket->custom;

	if(getMicroTime() - timer->creationTime > timer->timeout) { // connection timed out
		logWarning("Asynchronous connection on socket %d timed out", socket->fd);
		closeSocket(socket);
		triggerEvent(socket, "disconnect");
		return true;
	}

	// Initialize timeout
	struct timeval tv = {0, 0};

	// Initialize write fd set
	fd_set fdset;
	FD_ZERO(&fdset);
	FD_SET(socket->fd, &fdset);

	// Select socket for write flag (connected)
	int ret;
	if((ret = select(socket->fd + 1, NULL, &fdset, NULL, &tv)) < 0) {
#ifdef WIN32
		if(WSAGetLastError() != WSAEINTR) {
			char *error = g_win32_error_message(WSAGetLastError());
			logError("Error selecting socket %d for write flag (connected) while polling: %s", socket->fd, error);
			free(error);
#else
		if(errno != EINTR) {
			logSystemError("Error selecting socket %d for write flag (connected) while polling", socket->fd);
#endif
			closeSocket(socket);
			triggerEvent(socket, "disconnect");
			return true;
		}

		// EINTR at this point means the socket is just not connected yet, so we can safely return and continue polling another time
		return false;
	} else if(ret > 0) { // there is a write flag on the socket
		// Socket selected for write, check if we're indeed connected
		int valopt;
		socklen_t lon = sizeof(int);
		if(getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void*) (&valopt), &lon) < 0) {
			logSystemError("getsockopt() failed on socket %d", socket->fd);
			closeSocket(socket);
			triggerEvent(socket, "disconnect");
			return true;
		} else if(valopt != 0) { // There was a connection error
			logSystemError("Asynchronous connection on socket %d failed", socket->fd);
			closeSocket(socket);
			triggerEvent(socket, "disconnect");
			return true;
		}

		logNotice("Asynchronously connected socket %d", socket->fd);
		socket->connected = true;
		triggerEvent(socket, "connected");
		enableSocketPolling(socket);
		return true;
	}

	// the socket doesn't have a write flag, so let's just wait until it's connected
	return false;
}

/**
 * Polls a socket and notifies the caller of whether it should be removed from the polling table afterwards
 *
 * @param socket	the socket to poll
 * @param fd_p		a pointer to an integer field to which the file descriptor of the socket should be written in case the socket should be removed from the polling table and could already be freed at that time
 * @result			true if the socket should be removed from the polling table after polling
 */
static bool pollSocket(Socket *socket, int *fd_p)
{
	*fd_p = socket->fd; // backup file descriptor

	if(!socket->connected) { // Socket is disconnected
		triggerEvent(socket, "disconnect");
		return true;
	}

	if(socket->type != SOCKET_SERVER && socket->type != SOCKET_SERVER_BLOCK) {
		int ret;
		if((ret = socketReadRaw(socket, poll_buffer, SOCKET_POLL_BUFSIZE)) < 0) {
			if(socket->connected) { // socket is still connected, so the error was not fatal
				triggerEvent(socket, "error");
				return false;
			} else { // socket was disconnected either by the peer or by a fatal error
				triggerEvent(socket, "disconnect");
				return true;
			}
		} else if(ret > 0) { // we actually read something
			triggerEvent(socket, "read", poll_buffer, ret);
		} // else nothing to read right now
	} else {
		Socket *clientSocket;

		if((clientSocket = socketAccept(socket)) != NULL) {
			triggerEvent(socket, "accept", clientSocket);
		} else {
			if(socket->connected) { // socket is still connected, so the error was not fatal
				triggerEvent(socket, "error");
				return false;
			} else { // socket was disconnected either by the peer or by a fatal error
				triggerEvent(socket, "disconnect");
				return true;
			}
		}
	}

	return false;
}
void httpListenerTask(void *param)
{
   uint_t i;
   uint_t counter;
   uint16_t clientPort;
   IpAddr clientIpAddr;
   HttpServerContext *context;
   HttpConnection* connection;
   Socket *socket;

   //Retrieve the HTTP server context
   context = (HttpServerContext *) param;

   //Process incoming connections to the server
   for(counter = 1; ; counter++)
   {
      //Debug message
      TRACE_INFO("Ready to accept a new connection...\r\n");

      //Limit the number of simultaneous connections to the HTTP server
      osWaitForSemaphore(&context->semaphore, INFINITE_DELAY);

      //Loop through available client connections
      for(i = 0; i < context->settings.maxConnections; i++)
      {
         //Point to the current connection
         connection = &context->connections[i];

         //Ready to service the client request?
         if(!connection->running)
         {
            //Accept an incoming connection
            socket = socketAccept(context->socket, &clientIpAddr, &clientPort);

            //Make sure the socket handle is valid
            if(socket != NULL)
            {
               //Debug message
               TRACE_INFO("Connection #%u established with client %s port %" PRIu16 "...\r\n",
                  counter, ipAddrToString(&clientIpAddr, NULL), clientPort);

               //Reference to the HTTP server settings
               connection->settings = &context->settings;
               //Reference to the HTTP server context
               connection->serverContext = context;
               //Reference to the new socket
               connection->socket = socket;

               //Set timeout for blocking functions
               socketSetTimeout(connection->socket, HTTP_SERVER_TIMEOUT);

               //The client connection task is now running...
               connection->running = TRUE;
               //Service the current connection request
               osSetEvent(&connection->startEvent);

               //We are done
               break;
            }
         }
      }
   }
}
Exemple #12
0
/* The main loop handles all connections and cleanup.
 * It returns if there are any problems with the listening socket.
 */
static void main_loop(void) {
  int optirun_socket_fd;
  struct clientsocket * first = 0; //pointer to the first socket
  struct clientsocket * last = 0; //pointer to the last socket
  struct clientsocket * curr = 0; //current pointer to a socket
  struct clientsocket * prev = 0; //previous pointer to a socket

  bb_log(LOG_INFO, "Started main loop\n");
  /* Listen for Optirun conections and act accordingly */
  while (bb_status.bb_socket != -1) {
    usleep(100000); //sleep 100ms to prevent 100% CPU time usage

    /* Accept a connection. */
    optirun_socket_fd = socketAccept(&bb_status.bb_socket, SOCK_NOBLOCK);
    if (optirun_socket_fd >= 0) {
      bb_log(LOG_DEBUG, "Accepted new connection\n", optirun_socket_fd, bb_status.appcount);

      /* add to list of sockets */
      curr = malloc(sizeof (struct clientsocket));
      curr->sock = optirun_socket_fd;
      curr->inuse = 0;
      curr->next = 0;
      if (last == 0) {
        first = curr;
        last = curr;
      } else {
        last->next = curr;
        last = curr;
      }
    }

    /* loop through all connections, removing dead ones, receiving/sending data to the rest */
    curr = first;
    prev = 0;
    while (curr != 0) {
      if (curr->sock < 0) {
        //remove from list
        if (curr->inuse > 0) {
          bb_status.appcount--;
          //stop X / card if there is no need to keep it running
          if ((bb_status.appcount == 0) && (bb_config.stop_on_exit)) {
            stop_secondary();
          }
        }
        if (last == curr) {
          last = prev;
        }
        if (prev == 0) {
          first = curr->next;
          free(curr);
          curr = first;
        } else {
          prev->next = curr->next;
          free(curr);
          curr = prev->next;
        }
      } else {
        //active connection, handle it.
        handle_socket(curr);
        prev = curr;
        curr = curr->next;
      }
    }
  }//socket server loop

  /* loop through all connections, closing all of them */
  curr = first;
  prev = 0;
  while (curr != 0) {
    //close socket if not already closed
    if (curr->sock >= 0) {
      socketClose(&curr->sock);
    }
    //remove from list
    if (curr->inuse > 0) {
      bb_status.appcount--;
    }
    if (last == curr) {
      last = prev;
    }
    if (prev == 0) {
      first = curr->next;
      free(curr);
      curr = first;
    } else {
      prev->next = curr->next;
      free(curr);
      curr = prev->next;
    }
  }
}
void
proxyAccept(int srv_fd,	struct proxyConnection	*ncp)
{
	SOCKET			src_fd, dst_fd;
//	struct linger linger;
	int				status;
		int			res;
		struct timeval tv;
		int pc, sc;
		int			ccount=0;
		
	ILOG("Accepting new connection.");
	
	if ((src_fd = socketAccept(srv_fd, &status)) == INVALID_SOCKET) {
		WLOG("Error accepting connection: %d", status);
		return;
	}

	#ifdef USE_FORK
		// fork here
		fd_set	rs, ws, es;
		int fdmax;

		int pid=fork();
	  switch(pid) {
	  case -1:    /* error */
	      closesocket(ncp->plain);
	      closesocket(ncp->secure->fd);
	      break;

	  case  0:    /* child */
  #endif

	ncp->inuse=1;

	if (!isClient) {
		DLOG("Trying to accept ssl connection");
		if (sslAccept(&ncp->secure, src_fd, keys, cervalidator, 0)) {
			WLOG("Error could not establish ssl connection");
			socketShutdown(src_fd);
			/* Gemtek add +++ */
#ifdef USE_FORK
      quit=1;
#endif
      /* Gemtek add --- */
			return;
		}
	}

	setSocketNonblock(src_fd);
/*
	linger.l_onoff = 1;
	linger.l_linger = 1;
	setsockopt(src_fd, SOL_SOCKET, SO_LINGER, (char *) &linger,sizeof(linger));
*/
	/* try to connect to remote end of tunnel */
	DLOG("Trying to connect server %s:%d", dst_host, dst_port);
	if ((dst_fd = socketConnect(dst_host, dst_port, &status)) == INVALID_SOCKET) {
		WLOG("Error connecting to server %s:%d", dst_host, dst_port);
		socketShutdown(src_fd);
		/* Gemtek add +++ */
#ifdef USE_FORK
    quit=1;
#endif
    /* Gemtek add --- */
		return;
	}
	
	if (isClient) {
		DLOG("Trying to establish an ssl connection to server %s:%d", dst_host, dst_port);
		if ((sslConnect(&ncp->secure, dst_fd, keys, ncp->sessionId, ncp->cipherSuite, cervalidator)) == INVALID_SOCKET) {
			WLOG("Error connecting to ssl server %s:%d", dst_host, dst_port);
			socketShutdown(src_fd);
			return;
		}
	}
	setSocketNonblock(dst_fd);
/*
	linger.l_onoff = 1;
	linger.l_linger = 1;
	setsockopt(dst_fd, SOL_SOCKET, SO_LINGER, (char *) &linger,sizeof(linger));
*/
	ncp->plain = isClient ? src_fd : dst_fd;
	ncp->plain_up=1;
	ncp->secure_up=1;
	ILOG("Connection established. plain_fd:%d secure_fd:%d", ncp->plain, ncp->secure->fd);	
	
	// handle remaining bytes in buffer.
	/*
	res=proxyReadwrite(ncp,1);
	if(res<0) {
		ncp->error=1;
		closeProxyConnection(ncp);
	}
	*/
	// fork here
#ifdef USE_FORK
		
		closesocket(srv_fd);
		fdmax=ncp->plain > ncp->secure->fd ? ncp->plain : ncp->secure->fd;
		while (!quit) {
			FD_ZERO(&rs);
			FD_ZERO(&ws);
			FD_ZERO(&es);
			
				FD_SET(ncp->plain,&rs);
				FD_SET(ncp->plain,&ws);
				FD_SET(ncp->plain,&es);
				FD_SET(ncp->secure->fd,&rs);
				FD_SET(ncp->secure->fd,&ws);
				FD_SET(ncp->secure->fd,&es);
			
			
			tv.tv_sec=10;
			tv.tv_usec=0;

			DLOG("select on %d open connections. fdmax: %d", ccount, fdmax);
			res=select(fdmax+1,&rs,NULL,&es,&tv);
//			DLOG("select returned: %d", res);
			DLOG("proxyAccept->select returned: %d %s errno=%d", res , strerror(errno), errno );

			if(res<0) {
				perror("select");
				continue;
			}
/*
			if(res==0)
				continue;
*/
			if(FD_ISSET(ncp->secure->fd,&es) || FD_ISSET(ncp->plain,&es)) {
				ncp->error=1;
				break;
			}

			sc=proxyReadwrite(ncp,1);
			if(sc<0) break;
			pc=proxyReadwrite(ncp,0);
			if(pc<0) break;
			
			if(ncp->done) {
				quit=1;
				break;
			}
		}
		closeProxyConnection(ncp);
		DLOG("done. exiting...");
		exit(0);
		break;

	default:
      closesocket(src_fd);
							/* server */
		break;
	}
#endif
}
Exemple #14
0
error_t ftpOpenFile(FtpClientContext *context, const char_t *path, uint_t flags)
{
   error_t error;
   uint_t replyCode;
   IpAddr ipAddr;
   uint16_t port;

   //Invalid context?
   if(context == NULL)
      return ERROR_INVALID_PARAMETER;

   //Open data socket
   context->dataSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
   //Failed to open socket?
   if(!context->dataSocket)
      return ERROR_OPEN_FAILED;

   //Start of exception handling block
   do
   {
      //Bind the socket to a particular network interface?
      if(context->interface != NULL)
      {
         //Associate the socket with the relevant interface
         error = socketBindToInterface(context->dataSocket, context->interface);
         //Any error to report?
         if(error) break;
      }

      //Set timeout for blocking operations
      error = socketSetTimeout(context->dataSocket, FTP_CLIENT_DEFAULT_TIMEOUT);
      //Any error to report?
      if(error) break;

      //Check data transfer direction
      if(flags & (FTP_FOR_WRITING | FTP_FOR_APPENDING))
      {
         //Maximize transmission throughput by using a large buffer
         error = socketSetTxBufferSize(context->dataSocket,
            FTP_CLIENT_SOCKET_MAX_TX_BUFFER_SIZE);
         //Any error to report?
         if(error) break;

         //Use a small buffer for the reception path
         error = socketSetRxBufferSize(context->dataSocket,
            FTP_CLIENT_SOCKET_MIN_RX_BUFFER_SIZE);
         //Any error to report?
         if(error) break;
      }
      else
      {
         //Use a small buffer for the transmission path
         error = socketSetTxBufferSize(context->dataSocket,
            FTP_CLIENT_SOCKET_MIN_TX_BUFFER_SIZE);
         //Any error to report?
         if(error) break;

         //Maximize reception throughput by using a large buffer
         error = socketSetRxBufferSize(context->dataSocket,
            FTP_CLIENT_SOCKET_MAX_RX_BUFFER_SIZE);
         //Any error to report?
         if(error) break;
      }

      //Set representation type
      if(flags & FTP_TEXT_TYPE)
      {
         //Use ASCII type
         error = ftpSetType(context, 'A');
         //Any error to report?
         if(error) break;
      }
      else
      {
         //Use image type
         error = ftpSetType(context, 'I');
         //Any error to report?
         if(error) break;
      }

      //Check transfer mode
      if(!context->passiveMode)
      {
         //Place the data socket in the listening state
         error = socketListen(context->dataSocket, 1);
         //Any error to report?
         if(error) break;

         //Retrieve local IP address
         error = socketGetLocalAddr(context->controlSocket, &ipAddr, NULL);
         //Any error to report?
         if(error) break;

         //Retrieve local port number
         error = socketGetLocalAddr(context->dataSocket, NULL, &port);
         //Any error to report?
         if(error) break;

         //Set the port to be used in data connection
         error = ftpSetPort(context, &ipAddr, port);
         //Any error to report?
         if(error) break;
      }
      else
      {
         //Enter passive mode
         error = ftpSetPassiveMode(context, &port);
         //Any error to report?
         if(error) break;

         //Establish data connection
         error = socketConnect(context->dataSocket, &context->serverAddr, port);
         //Connection to server failed?
         if(error) break;
      }

      //Format the command
      if(flags & FTP_FOR_WRITING)
         sprintf(context->buffer, "STOR %s\r\n", path);
      else if(flags & FTP_FOR_APPENDING)
         sprintf(context->buffer, "APPE %s\r\n", path);
      else
         sprintf(context->buffer, "RETR %s\r\n", path);

      //Send the command to the server
      error = ftpSendCommand(context, context->buffer, &replyCode);
      //Any error to report?
      if(error) break;

      //Check FTP response code
      if(!FTP_REPLY_CODE_1YZ(replyCode))
      {
         //Report an error
         error = ERROR_UNEXPECTED_RESPONSE;
         break;
      }

      //Check transfer mode
      if(!context->passiveMode)
      {
         //Wait for the server to connect back to the client's data port
         Socket *socket = socketAccept(context->dataSocket, NULL, NULL);

         //No connection request?
         if(!socket)
         {
            //Report an error
            error = ERROR_FAILURE;
            break;
         }

         //Close the listening socket
         socketClose(context->dataSocket);
         //Save socket handle
         context->dataSocket = socket;

         //Set timeout for blocking operations
         error = socketSetTimeout(context->dataSocket, FTP_CLIENT_DEFAULT_TIMEOUT);
         //Any error to report?
         if(error) break;
      }

      //End of exception handling block
   } while(0);

   //Any error to report?
   if(error)
   {
      //Clean up side effects
      socketClose(context->dataSocket);
      context->dataSocket = NULL;
   }

   //Return status code
   return error;
}
void tcpDiscardListenerTask(void *param)
{
   error_t error;
   uint16_t clientPort;
   IpAddr clientIpAddr;
   Socket *serverSocket;
   Socket *clientSocket;
   DiscardServiceContext *context;
   OsTask *task;

   //Point to the listening socket
   serverSocket = (Socket *) param;

   //Main loop
   while(1)
   {
      //Accept an incoming connection
      clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort);
      //Check whether a valid connection request has been received
      if(!clientSocket) continue;

      //Debug message
      TRACE_INFO("Discard service: connection established with client %s port %" PRIu16 "\r\n",
         ipAddrToString(&clientIpAddr, NULL), clientPort);

      //Adjust timeout
      error = socketSetTimeout(clientSocket, DISCARD_TIMEOUT);

      //Any error to report?
      if(error)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Allocate resources for the new connection
      context = osAllocMem(sizeof(DiscardServiceContext));

      //Failed to allocate memory?
      if(!context)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Record the handle of the newly created socket
      context->socket = clientSocket;

      //Create a task to service the current connection
      task = osCreateTask("TCP Discard Connection", tcpDiscardConnectionTask,
         context, DISCARD_SERVICE_STACK_SIZE, DISCARD_SERVICE_PRIORITY);

      //Did we encounter an error?
      if(task == OS_INVALID_HANDLE)
      {
         //Close socket
         socketClose(clientSocket);
         //Release resources
         osFreeMem(context);
      }
   }
}