Exemplo n.º 1
0
//
// Receive and return bytes up to and including the bytes specified by pContentArg & ContentLength.
//
extern bool sockReceiveUntilContent(sock * pSock, void * pBufferArg, size_t BufferSize,
                                    const void * pContentArg, size_t ContentLength, size_t * pBytesReceived)
{
  char * pBuffer  = (char * ) pBufferArg;
  char * pContent = (char * ) pContentArg;

  const int BufferBytesAvailable = RECEIVE_BUFFER_SIZE-pSock->m_BytesReceived;

  if (pSock->m_Closed)
    return false;

  if (BufferBytesAvailable > 0) {
    recvsize_t NewBytesReceived = recv(pSock->m_Socket,
                                       pSock->m_pReceiveBuffer+pSock->m_BytesReceived,
                                       BufferBytesAvailable, 0);

    if (WouldBlock(pSock, NewBytesReceived)) {
      //
      // If we would block, then there are no bytes available to read, but there
      // may be bytes already in the receive buffer, so we need to continue to 
      // allow those bytes to be consumed.
      //
      NewBytesReceived = 0;
    }
    else if (CheckReceiveError(pSock, NewBytesReceived)) {
      return false;
    }

    pSock->m_BytesReceived += NewBytesReceived;
  }

  if (pSock->m_BytesReceived >= ContentLength) {
    const char * pFirst = pSock->m_pReceiveBuffer;
    const char * pLast  = pFirst + pSock->m_BytesReceived - ContentLength;

    //
    // Search for content bytes in the receive buffer.
    //
    for (; pFirst <= pLast; pFirst++) {
      if (memcmp(pFirst, pContent, ContentLength) == 0) {
        // Consume...
        const size_t Span = oosmos_Min((pFirst-pSock->m_pReceiveBuffer)+ContentLength, BufferSize);
        memcpy(pBuffer, pSock->m_pReceiveBuffer, Span);
        *pBytesReceived = Span;

        // Shift...
        pSock->m_BytesReceived -= Span;
        memcpy(pSock->m_pReceiveBuffer, pSock->m_pReceiveBuffer+Span, pSock->m_BytesReceived);
        return true;
      }
    }

    return false;
  }

  return false;
}
Exemplo n.º 2
0
extern bool sockReceive(sock * pSock, void * pBuffer, size_t BufferSize, size_t * pBytesReceived)
{
  if (pSock->m_Closed)
    return false;

  if (pSock->m_BytesReceived < BufferSize) {
    recvsize_t NewBytesReceived = recv(pSock->m_Socket, 
                                       pSock->m_pReceiveBuffer+pSock->m_BytesReceived,
                                       RECEIVE_BUFFER_SIZE-pSock->m_BytesReceived,
                                       0);

    if (WouldBlock(pSock, NewBytesReceived)) {
      //
      // If we would block, then there are no bytes available to read, but there
      // may be bytes already in the receive buffer, so we need to continue to 
      // allow those bytes to be consumed.
      //
      NewBytesReceived = 0;
    }
    else if (CheckReceiveError(pSock, NewBytesReceived)) {
      return false;
    }

    pSock->m_BytesReceived += NewBytesReceived;
  }

  if (pSock->m_BytesReceived > 0) {
    // Consume...
    const size_t Span = oosmos_Min(pSock->m_BytesReceived, BufferSize);
    memcpy(pBuffer, pSock->m_pReceiveBuffer, Span);
    *pBytesReceived = Span;

    // Shift...
    pSock->m_BytesReceived -= Span;
    memcpy(pSock->m_pReceiveBuffer, pSock->m_pReceiveBuffer+Span, pSock->m_BytesReceived);

    return true;
  }

  return false;
}
Exemplo n.º 3
0
	FollowUp ListeningSocket::Perform (const Notification & n) {
	
		FollowUp retr;
		
		if (do_shutdown) {
		
			retr.Remove=true;
			
			return retr;
			
		}
		
		for (;;) {
		
			struct sockaddr_storage addr;
			socklen_t len=sizeof(addr);
			auto socket=accept(
				this->socket,
				reinterpret_cast<struct sockaddr *>(&addr),
				&len
			);
			//	Check for failure
			if (socket==-1) {
			
				//	Was the failure just because
				//	the operation would block?
				if (WouldBlock()) break;
				
				//	Were we interrupted?
				if (WasInterrupted()) continue;
				
				//	Actually an error
				Raise();
				
			}
			
			//	Increment statistic
			++retr.Accepted;
			
			auto ep=GetEndpoint(&addr);
			SmartPointer<Connection> conn;
			try {
				
				conn=SmartPointer<Connection>::Make(
					socket,
					ep.IP,
					ep.Port,
					this->ep.IP,
					this->ep.Port,
					this->ep.Receive,
					this->ep.Disconnect
				);
				
			} catch (...) {
			
				//	Make sure the socket gets
				//	closed
				close(socket);
				
				throw;
				
			}
			
			//	Fire off a callback to handle this
			//	incoming connections
			#pragma GCC diagnostic push
			#pragma GCC diagnostic ignored "-Wpedantic"
			retr.Action.Add([
				this,
				conn=std::move(conn),
				socket
			] (SmartPointer<ChannelBase> channel) mutable {
				
				FollowUp f;
				
				//	Should this connection be allowed?
				if (this->ep.Accept) {
				
					try {
						
						//	If the connection is not admitted,
						//	return at once, the connection will
						//	automatically be dropped by the Socket
						//	RAII container
						if (!this->ep.Accept(AcceptEvent{
							conn->IP(),
							conn->Port(),
							this->ep.IP,
							this->ep.Port
						})) return f;
						
					} catch (...) {
					
						//	Consider throwing the same thing
						//	as returning false
						return f;
						
					}
					
				}
				
				//	The connection is allowed
				++f.Incoming;
				
				//	Fire the connect handler
				if (this->ep.Connect) {
				
					ConnectEvent event;
					event.Conn=conn;
					
					try {
						
						this->ep.Connect(std::move(event));
						
					//	Ignore user exceptions
					} catch (...) {	}
					
				}
				
				//	Add the connection
				f.Add=Channel{
					socket,
					std::move(conn).Convert<ChannelBase>()
				};
				
				return f;
				
			});
			#pragma GCC diagnostic pop
			
		}
		
		return retr;
		
	}