예제 #1
0
void Socket::recv_all() {
	static char buf[MAXPACKET];
	while(true) {
		sockaddr addr;
		socklen_t addrlen = sizeof(struct sockaddr);
		int len = recvfrom(socket, buf, MAXPACKET, MSG_DONTWAIT, &addr, &addrlen);
		if(len < 4)
			break;

		string s = string((char *)&addr, addrlen);
		int id;
		memcpy((void*)&id, (void*)buf, 4);
		id = ntohl(id);
		pair<string,int> s_id(s, id);

		SocketConnection *sc;
		if(connections.count(s_id) == 0) {
			if(!listening)
				continue;
			sc = new SocketConnection(socket, &addr, addrlen, SERVER_ID, id);
			new_connections.push(sc);
			connections[s_id] = sc;
		} else {
			sc = connections[s_id];
		}

		sc->recv_data(buf, len);
	}
}
예제 #2
0
bool SocketAcceptor::onData( SocketServer& server, socket_handle s )
{
  SocketConnections::iterator i = m_connections.find( s );
  if ( i == m_connections.end() ) return false;
  SocketConnection* pSocketConnection = i->second;
  return pSocketConnection->read( *this, server );
}
예제 #3
0
void SocketInitiator::onDisconnect( SocketConnector&, int s )
{ QF_STACK_PUSH(SocketInitiator::onDisconnect)

  SocketConnections::iterator i = m_connections.find( s );
  SocketConnections::iterator j = m_pendingConnections.find( s );

  SocketConnection* pSocketConnection = 0;
  if( i != m_connections.end() ) 
	  pSocketConnection = i->second;
  if( j != m_pendingConnections.end() )
	  pSocketConnection = j->second;
  if( !pSocketConnection )
	  return;

  setDisconnected( pSocketConnection->getSession()->getSessionID() );

  Session* pSession = pSocketConnection->getSession();
  if ( pSession )
  {
    pSession->disconnect();
    setDisconnected( pSession->getSessionID() );
  }

  delete pSocketConnection;
  m_connections.erase( s );
  m_pendingConnections.erase( s );

  QF_STACK_POP
}
예제 #4
0
ConnectionPtr SocketConnection::acceptSync()
{
    LB_TS_THREAD( _recvThread );
    if( !isListening( ))
        return 0;

    LBASSERT( _overlappedAcceptData );
    LBASSERT( _overlappedSocket != INVALID_SOCKET );
    if( _overlappedSocket == INVALID_SOCKET )
        return 0;

    // complete accept
    DWORD got   = 0;
    DWORD flags = 0;

    if( !WSAGetOverlappedResult( _readFD, &_overlappedRead, &got, TRUE,
                                 &flags ))
    {
        LBWARN << "Accept completion failed: " << lunchbox::sysError
               << ", closing socket" << std::endl;
        close();
        return 0;
    }

    sockaddr_in* local     = 0;
    sockaddr_in* remote    = 0;
    int          localLen  = 0;
    int          remoteLen = 0;
    GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16,
                          sizeof( sockaddr_in ) + 16, (sockaddr**)&local,
                          &localLen, (sockaddr**)&remote, &remoteLen );
    _tuneSocket( _overlappedSocket );

    ConstConnectionDescriptionPtr description = getDescription();
    SocketConnection* newConnection = new SocketConnection;
    ConnectionPtr connection( newConnection ); // to keep ref-counting correct

    newConnection->_readFD  = _overlappedSocket;
    newConnection->_writeFD = _overlappedSocket;

#ifndef _WIN32
    //fcntl( _overlappedSocket, F_SETFL, O_NONBLOCK );
#endif

    newConnection->_initAIORead();
    _overlappedSocket       = INVALID_SOCKET;

    newConnection->_setState( STATE_CONNECTED );
    ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
    newDescription->bandwidth = description->bandwidth;
    newDescription->port = ntohs( remote->sin_port );
    newDescription->setHostname( getHostName( *remote ));

    LBDEBUG << "accepted connection from " << newDescription->getHostname()
           << ":" << newDescription->port << std::endl;
    return connection;
}
예제 #5
0
void OutputSocket::removeFirstConnection()
{
	SocketConnection *connection = this->m_connections[0];
	InputSocket *inputSocket = connection->getToSocket();
	if (inputSocket != NULL) {
		inputSocket->setConnection(NULL);
	}
	this->m_connections.erase(this->m_connections.begin());
}
예제 #6
0
bool SocketInitiator::onData( SocketConnector& connector, int s )
{ QF_STACK_PUSH(SocketInitiator::onData)

  SocketConnections::iterator i = m_connections.find( s );
  if ( i == m_connections.end() ) return false;
  SocketConnection* pSocketConnection = i->second;
  return pSocketConnection->read( connector );

  QF_STACK_POP
}
SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket)
{
	SocketConnection *newconnection = new SocketConnection();
	newconnection->setFromSocket(fromSocket);
	newconnection->setToSocket(toSocket);
	fromSocket->addConnection(newconnection);
	toSocket->setConnection(newconnection);
	links.push_back(newconnection);
	return newconnection;
}
예제 #8
0
void SocketInitiator::onWrite( SocketConnector& connector, int s )
{ QF_STACK_PUSH(SocketInitiator::onWrite)

  SocketConnections::iterator i = m_connections.find( s );
  if ( i == m_connections.end() ) return ;
  SocketConnection* pSocketConnection = i->second;
  if( pSocketConnection->processQueue() )
    pSocketConnection->unsignal();
  
  QF_STACK_POP
}
예제 #9
0
void SocketAcceptor::onDisconnect( SocketServer&, socket_handle s )
{
  SocketConnections::iterator i = m_connections.find( s );
  if ( i == m_connections.end() ) return ;
  SocketConnection* pSocketConnection = i->second;

  Session* pSession = pSocketConnection->getSession();
  if ( pSession ) pSession->disconnect();

  delete pSocketConnection;
  m_connections.erase( s );
}
예제 #10
0
void SocketConnection::onHeartbeat(int theFd, short theEvt, void *theArg)
{
    SocketConnection* connection = (SocketConnection*) theArg;
    connection->heartbeatTimerEvtM = NULL;

    int heartbeatInterval = connection->protocolM->getHeartbeatInterval();
    if (heartbeatInterval > 0)
    {
        connection->protocolM->asynHandleHeartbeat(connection->fdM, connection->selfM);
    }

    connection->startHeartbeatTimer();
}
예제 #11
0
void SocketInitiator::onConnect( SocketConnector&, int s )
{ QF_STACK_PUSH(SocketInitiator::onConnect)

  SocketConnections::iterator i = m_pendingConnections.find( s );
  if( i == m_pendingConnections.end() ) return;
  SocketConnection* pSocketConnection = i->second;
  
  m_connections[s] = pSocketConnection;
  m_pendingConnections.erase( i );
  setConnected( pSocketConnection->getSession()->getSessionID() );
  pSocketConnection->onTimeout();

  QF_STACK_POP
}
예제 #12
0
WriteBufferOperation *OutputSocket::findAttachedWriteBufferOperation() const
{
	unsigned int index;
	for (index = 0; index < this->m_connections.size(); index++) {
		SocketConnection *connection = this->m_connections[index];
		NodeBase *node = connection->getToNode();
		if (node->isOperation()) {
			NodeOperation *operation = (NodeOperation *)node;
			if (operation->isWriteBufferOperation()) {
				return (WriteBufferOperation *)operation;
			}
		}
	}
	return NULL;
}
예제 #13
0
gboolean SocketConnection::NegotiateTLSCb(GIOChannel* gio, gboolean isSocketEncrypted, gpointer data, const GError* error)
{
	SocketConnection *socketConnection = reinterpret_cast<SocketConnection *>( data );

	// Temp reference to keep SocketConnection reference alive while we're executing it
	MojRefCountedPtr<SocketConnection> temp(socketConnection);

	// Note: error should not be freed

	if(error == NULL && isSocketEncrypted)
		socketConnection->TLSReady();
	else
		socketConnection->TLSError(error);

	return true;
}
예제 #14
0
gboolean SocketConnection::SocketConnectCb(GIOChannel* gio, gpointer data, const GError* error)
{
	SocketConnection *socketConnection = reinterpret_cast<SocketConnection *>( data );
	assert(data);
	
	// Temp reference to keep SocketConnection reference alive while we're executing it
	MojRefCountedPtr<SocketConnection> temp(socketConnection);

	// Note: error should not be freed

	socketConnection->m_connectTimer.Cancel();

	if(error == NULL)
		socketConnection->Connected();
	else
		socketConnection->ConnectError(error);
	
	return true;
}
예제 #15
0
void OutputSocket::relinkConnections(OutputSocket *relinkToSocket, bool single)
{
	if (isConnected()) {
		if (single) {
			SocketConnection *connection = this->m_connections[0];
			connection->setFromSocket(relinkToSocket);
			relinkToSocket->addConnection(connection);
			this->m_connections.erase(this->m_connections.begin());
		}
		else {
			unsigned int index;
			for (index = 0; index < this->m_connections.size(); index++) {
				SocketConnection *connection = this->m_connections[index];
				connection->setFromSocket(relinkToSocket);
				relinkToSocket->addConnection(connection);
			}
			this->m_connections.clear();
		}
	}
}
예제 #16
0
ConnectionPtr SocketConnection::acceptSync()
{
    if( !isListening( ))
        return 0;

    sockaddr_in newAddress;
    socklen_t   newAddressLen = sizeof( newAddress );

    Socket    fd;
    unsigned  nTries = 1000;
    do
        fd = ::accept( _readFD, (sockaddr*)&newAddress, &newAddressLen );
    while( fd == INVALID_SOCKET && errno == EINTR && --nTries );

    if( fd == INVALID_SOCKET )
    {
      LBWARN << "accept failed: " << lunchbox::sysError << std::endl;
        return 0;
    }

    _tuneSocket( fd );

    ConstConnectionDescriptionPtr description = getDescription();
    SocketConnection* newConnection = new SocketConnection;

    newConnection->_readFD      = fd;
    newConnection->_writeFD     = fd;
    newConnection->_setState( STATE_CONNECTED );
    ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
    newDescription->bandwidth = description->bandwidth;
    newDescription->port = ntohs( newAddress.sin_port );
    newDescription->setHostname( inet_ntoa( newAddress.sin_addr ));

    LBDEBUG << "Accepted " << newDescription->toString() << std::endl;
    return newConnection;
}
예제 #17
0
void SocketServer::start() {
	struct sockaddr_storage remoteaddr; // client address
	socklen_t addrlen;
	char remoteIP[INET6_ADDRSTRLEN];
//	sigset_t mask;
//	sigset_t orig_mask;

	// key = connection id
	std::map<int, SocketConnection*> connections;

//	/**
//	 * I'm not sure of this signal handling code, but for now it works:
//	 * I register a signal handler for the process, then in the handler I look if it's a SIGKILL for the thread, then
//	 * flag it as killed.
//	 * The sigmask code, I think, it's for handling correctly a signal while pselect is waiting, then exit from it
//	 */
//	struct sigaction act;
//
//	memset (&act, 0, sizeof(act));
//	act.sa_handler = signal_handler;
//
//	/* should shut down on SIGTERM. */
//	if (sigaction(SIGTERM, &act, 0)) {
//		perror ("sigaction");
//		throw std::exception();
//	}
//
//	sigemptyset (&mask);
//	sigaddset (&mask, SIGPIPE);
//
//	if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) {
//		perror ("sigprocmask");
//		throw std::exception();
//	}

	// main loop
	for(;;) {
        read_fds = master; // copy it
        if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
            perror("select");
            exit(4);
        }

        int i;
        // run through the existing connections looking for data to read
        for(i = 0; i <= fdmax; i++) {
            if (FD_ISSET(i, &read_fds)) { // we got one!!
            	if (i == listenfd) {
            		// handle new connection
            		addrlen = sizeof remoteaddr;
            		int connfd = accept(listenfd, (struct sockaddr *)&remoteaddr, &addrlen);

            		if (connfd == -1) {
            			perror("accept() error");
            		} else {
            			FD_SET(connfd, &master); // add to master set
						if (connfd > fdmax) {    // keep track of the max
							fdmax = connfd;
						}
						printf("new connection from %s on "
							"socket %d\n",
							inet_ntop(remoteaddr.ss_family,
								get_in_addr((struct sockaddr*)&remoteaddr),
								remoteIP, INET6_ADDRSTRLEN),
							connfd);
            		}

            	} else {
            		// handle data from a client

            		auto found = connections.find(i);
            		if (found == connections.end()) {
            			connections[i] = new SocketConnection(i);
            		}
            		SocketConnection *connection = connections[i];


            		try {
            		    int rcvd;

            			rcvd = connection->read(request_buffer, REQUEST_BUFFER_SIZE);

            			if (rcvd < 0)    // receive error
            			{
            				perror("recv() error");
            				throw std::exception();
            			}
            			else if (rcvd == 0)
            			{
            				fprintf(stderr,"Client disconnected unexpectedly.\n");
            				throw std::exception();
            			}

						if (data_received(connection, request_buffer, rcvd)) {
							connections.erase(i);
							delete(connection);

							FD_CLR(i, &master); // remove from master set
						}
            		} catch (std::exception &e) {
            			std::cerr << "exception handling request: " << e.what() << std::endl;
            			connections.erase(i);
            			connection_closed(connection);
            			delete(connection);
            			FD_CLR(i, &master); // remove from master set
            		}
            	}
            }
        }
	}
}
예제 #18
0
void on_read(int theFd, short theEvt, void *theArg)
{
    SocketConnection* connection = (SocketConnection*)theArg;
    connection->asynRead(theFd, theEvt);
}
예제 #19
0
void on_write(int theFd, short theEvt, void *theArg)
{
    SocketConnection* connection = (SocketConnection*)theArg;
    connection->asynWrite(theFd, theEvt);
}