Example #1
0
/* Escucha los pedidos de conexion para iniciar una descarga por parte del servidor */
status
InitDownloader(void)
{
	int ssock;
	
	/* Preparo el puerto que va a escuchar los pedidos de conexion de transferencia */
	if( (passive_s=prepareTCP(client_host,client_port,prepareServer)) < 0 ) {
		return FATAL_ERROR;
	}	
	if( (listenTCP(passive_s,10)) < 0 ) {
		return FATAL_ERROR;
	}
	
	while(1) {
		ssock = acceptTCP(passive_s);
		setSocketTimeout(ssock,TIMEOUT_DEFAULT);
		switch(fork()){
			case 0: 
				NewDownload(ssock);
				exit(EXIT_SUCCESS);
				break;
			case -1:
				return FATAL_ERROR;
				break;
			default:
				/* Sigo escuchando */
				break;
		}
		close(ssock);
	}	
	closeTCP(passive_s);
	
	return OK;
	
}
Example #2
0
static unsigned long 
SendRequest(u_size op_code,u_size total_objects,void *packet, u_size size)
{
	header_t header;
	void *to_send;
	int socket;
	int ret;
	ack_t *ack_ptr;
	void *data;
	u_size header_size;
	
	/* Tipo de pedido */
	header.opCode = op_code;
	header.total_objects = total_objects;
	/* Identificacion del usuario */
	strcpy(header.user,log_user);
	strcpy(header.passwd,log_passwd);
	header_size = GetHeaderData(header, &data);	
	/* Concateno los paquetes header y pedido */
	if( (to_send = malloc(header_size+size)) == NULL )
		return CONNECT_ERROR;	
	memmove(to_send, data, header_size);
	free(data);
	/* Chequeo si realmente se manda un paquete asociado al pedido */
	if( packet != NULL ) {
		memmove(to_send+header_size, packet, size);
	}	
	/* Me conecto al servidor */
	if( (socket=connectTCP(server_host,server_port)) < 0 ){
		free(to_send);
		return CONNECT_ERROR;
	}

	setSocketTimeout(socket,TIMEOUT_DEFAULT);
	/* Mando el paquete */
	sendTCP(socket, to_send,header_size+size);
	free(to_send);
	if(exitPipe==1)
	{
	    exitPipe=0;
	    close(socket);
	    return TIMEOUT_ERROR;
	}
	
	/* Espero por la respuesta del servidor */
	ack_ptr = receiveTCP(socket);
	if(ack_ptr==NULL)
	{
	    close(socket);
	    return TIMEOUT_ERROR;
	}
	ret = ack_ptr->ret_code;
	free(ack_ptr);
	/* Cierro la conexion????? */
	close(socket);
	return ret;
}
Example #3
0
static download_header_t
SendDownloadRequest(void *packet, u_size size)
{
	header_t header;
	void *to_send;
	int socket;
	download_header_t download_info;
	void *data;
	u_size header_size;
	void *ack_data;
	
	download_info.ret_code = CONNECT_ERROR;
	
	/* Tipo de pedido */
	header.opCode = __DOWNLOAD__;
	header.total_objects = 1;
	/* Identificacion del usuario */
	strcpy(header.user,log_user);
	strcpy(header.passwd,log_passwd);	
	header_size = GetHeaderData(header, &data);	
	/* Concateno los paquetes header y pedido */
	if( (to_send = malloc(header_size+size)) == NULL )
		return download_info;	
	memmove(to_send, data, header_size);
	memmove(to_send+header_size, packet, size);
	free(data);
	/* Me conecto al servidor */
	if( (socket=connectTCP(server_host,server_port)) < 0 ){
		free(to_send);
		return download_info;
	}
	setSocketTimeout(socket,TIMEOUT_DEFAULT);
	/* Mando el paquete */
	sendTCP(socket, to_send,header_size+size);
	free(to_send);
	if(exitPipe==1)
	{
	    exitPipe=0;
	    close(socket);
	    return download_info;
	}
	
	/* Espero por la respuesta del servidor */
	ack_data = receiveTCP(socket);
	if(ack_data==NULL)
	{
	    close(socket);
	    return download_info;
	}
	GetDownloadHeaderPack(ack_data, &download_info);
	/* Cierro la conexion????? */
	close(socket);
	return download_info;
	
}
 bool tryAndRun(cybozu::Socket& client)
 {
     int expected = Sleep;
     if (!state_.compare_exchange_strong(expected, Ready)) return false;
     try {
         s_[0].moveFrom(client);
         s_[1].connect(opt_.serverAddr, opt_.serverPort, opt_.socketTimeoutS * 1000);
         setSocketTimeout(s_[1], opt_.socketTimeoutS);
         state_ = Running2;
     } catch (std::exception& e) {
         s_[0].close();
         s_[1].close();
         state_ = Sleep;
     }
     return true;
 }
Example #5
0
static status
SendSignal(u_size op_code, void *packet, u_size size)
{
	header_t header;
	void *to_send;
	int socket;
	u_size header_size;
	void *data;
	
	/* Tipo de senial */
	header.opCode = op_code;
	header.total_objects = 1;
	/* Identificacion del usuario */
	strcpy(header.user,log_user);
	strcpy(header.passwd,log_passwd);
	/* Concateno los paquetes header y pedido */
	header_size = GetHeaderData(header, &data);	
	if( (to_send = malloc(header_size+size)) == NULL )
		return ERROR;	
	memmove(to_send, data, header_size);
	memmove(to_send + header_size,packet,size);
	free(data);
	/* Me conecto al servidor */
	if( (socket=connectTCP(server_host,server_port)) < 0 ){
		free(to_send);
		return ERROR;
	}
	setSocketTimeout(socket,TIMEOUT_DEFAULT);
	/* Mando el paquete */
	sendTCP(socket, to_send,header_size+size);
	free(to_send);
	if(exitPipe==1)
	{
	    exitPipe=0;
	    close(socket);
	    return ERROR;
	}
	
	close(socket);
	return OK;	
}
Example #6
0
/*----------------------------------------------------------------------------*/
void http_accept(int conSocket, int timeoutSecs, int keepAlive) {
    /* Init request structure */
    HttpRequest* request = malloc(sizeof(HttpRequest));
    socketFd = conSocket;
    memset((void*)request, 0, sizeof(HttpRequest));
    char* urlBuffer = malloc(128);
    request->url = &urlBuffer;
    request->urlMaxLength = 128;
    LOG_CON(INFO, socketFd, "New HTTP request incoming");
    /* Set timeout on socket */
    if (0 > setSocketTimeout(socketFd, timeoutSecs)) {
        LOG_CON(ERROR, socketFd, "Could not set timeout on client socket");
        close(socketFd);
        PANIC("Could not timeout on socket");
    }
    do {
        if (0 != http_readRequest(request)) {
            LOG_CON(socketFd, ERROR, strerror(errno));
            close(socketFd);
            PANIC("Something wrong with the HTTP header");
        }
        switch (request->type) {
            case GET:
            case HEAD:
                http_processGetHead(request);
                break;
            case OTHER:
                http_sendDefaultResponse(405);
                close(socketFd);
                LOG_CON(WARN, socketFd, "Unsupported request type");
                PANIC("Bad request");
            default:
                assert(!"SHOULD NEVER HAPPEND");
        }
    } while (keepAlive);
    close(socketFd);
}
int main(int argc, char *argv[])
    try
{
    const Option opt(argc, argv);
    cybozu::Socket server;
    server.bind(opt.recvPort);
    ThreadRunner cmdRunner;
    cmdRunner.set(std::thread(cmdThread, opt));
    std::vector<std::unique_ptr<Repeater>> worker;
    for (size_t i = 0; i < opt.threadNum; i++) {
        worker.emplace_back(new Repeater(opt, (int)i));
    }
    for (;;) {
RETRY:
        while (!g_quit && !server.queryAccept()) {
        }
        if (g_quit) break;
        cybozu::SocketAddr addr;
        cybozu::Socket client;
        server.accept(client, &addr);
        setSocketTimeout(client, opt.socketTimeoutS);
        if (opt.verbose) cybozu::PutLog(cybozu::LogInfo, "accept addr %s", addr.toStr().c_str());
        while (!g_quit) {
            for (size_t i = 0; i < opt.threadNum; i++) {
                if (worker[i]->tryAndRun(client)) {
                    goto RETRY;
                }
            }
            waitMsec(100);
        }
        waitMsec(100);
    }
    if (opt.verbose) puts("main end");
} catch (std::exception& e) {
    cybozu::PutLog(cybozu::LogError, "error: %s", e.what());
    return 1;
}
bool LLPluginMessagePipe::pump(F64 timeout)
{
	bool result = true;
	
	if(mSocket)
	{
		apr_status_t status;
		apr_size_t size;
		
		if(!mOutput.empty())
		{
			// write any outgoing messages
			size = (apr_size_t)mOutput.size();
			
			setSocketTimeout(0);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			status = apr_socket_send(
					mSocket->getSocket(),
					(const char*)mOutput.data(),
					&size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if(status == APR_SUCCESS)
			{
				// success
				mOutput = mOutput.substr(size);
			}
			else if(APR_STATUS_IS_EAGAIN(status))
			{
				// Socket buffer is full... 
				// remove the written part from the buffer and try again later.
				mOutput = mOutput.substr(size);
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}

		// FIXME: For some reason, the apr timeout stuff isn't working properly on windows.
		// Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead.
#if LL_WINDOWS
		if(result)
		{
			if(timeout != 0.0f)
			{
				ms_sleep((int)(timeout * 1000.0f));
				timeout = 0.0f;
			}
		}
#endif
		
		// Check for incoming messages
		if(result)
		{
			char input_buf[1024];
			apr_size_t request_size;
			
			// Start out by reading one byte, so that any data received will wake us up.
			request_size = 1;
			
			// and use the timeout so we'll sleep if no data is available.
			setSocketTimeout((apr_interval_time_t)(timeout * 1000000));

			while(1)		
			{
				size = request_size;

//				LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL;

				status = apr_socket_recv(
						mSocket->getSocket(), 
						input_buf, 
						&size);

//				LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;
				
				if(size > 0)
					mInput.append(input_buf, size);

				if(status == APR_SUCCESS)
				{
//					llinfos << "success, read " << size << llendl;

					if(size != request_size)
					{
						// This was a short read, so we're done.
						break;
					}
				}
				else if(APR_STATUS_IS_TIMEUP(status))
				{
//					llinfos << "TIMEUP, read " << size << llendl;

					// Timeout was hit.  Since the initial read is 1 byte, this should never be a partial read.
					break;
				}
				else if(APR_STATUS_IS_EAGAIN(status))
				{
//					llinfos << "EAGAIN, read " << size << llendl;

					// We've been doing partial reads, and we're done now.
					break;
				}
				else
				{
					// some other error
					// Treat this as fatal.
					ll_apr_warn_status(status);

					if(mOwner)
					{
						mOwner->socketError(status);
					}
					result = false;
					break;
				}

				// Second and subsequent reads should not use the timeout
				setSocketTimeout(0);
				// and should try to fill the input buffer
				request_size = sizeof(input_buf);
			}
			
			processInput();
		}
	}

	if(!result)
	{
		// If we got an error, we're done.
		LL_INFOS("Plugin") << "Error from socket, cleaning up." << LL_ENDL;
		delete this;
	}
	
	return result;	
}
Example #9
0
bool LLPluginMessagePipe::pumpInput(F64 timeout)
{
	bool result = true;

	if(mSocket)
	{
		apr_status_t status;
		apr_size_t size;

		// FIXME: For some reason, the apr timeout stuff isn't working properly on windows.
		// Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead.
#if LL_WINDOWS
		if(result)
		{
			if(timeout != 0.0f)
			{
				ms_sleep((int)(timeout * 1000.0f));
				timeout = 0.0f;
			}
		}
#endif
		
		// Check for incoming messages
		if(result)
		{
			char input_buf[1024];
			apr_size_t request_size;
			
			if(timeout == 0.0f)
			{
				// If we have no timeout, start out with a full read.
				request_size = sizeof(input_buf);
			}
			else
			{
				// Start out by reading one byte, so that any data received will wake us up.
				request_size = 1;
			}
			
			// and use the timeout so we'll sleep if no data is available.
			setSocketTimeout((apr_interval_time_t)(timeout * 1000000));

			while(1)		
			{
				size = request_size;

//				LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL;

				status = apr_socket_recv(
						mSocket->getSocket(), 
						input_buf, 
						&size);

//				LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;
				
				if(size > 0)
				{
					LLMutexLock lock(&mInputMutex);
					mInput.append(input_buf, size);
				}

				if(status == APR_SUCCESS)
				{
					LL_DEBUGS("PluginSocket") << "success, read " << size << LL_ENDL;

					if(size != request_size)
					{
						// This was a short read, so we're done.
						break;
					}
				}
				else if(APR_STATUS_IS_TIMEUP(status))
				{
					LL_DEBUGS("PluginSocket") << "TIMEUP, read " << size << LL_ENDL;

					// Timeout was hit.  Since the initial read is 1 byte, this should never be a partial read.
					break;
				}
				else if(APR_STATUS_IS_EAGAIN(status))
				{
					LL_DEBUGS("PluginSocket") << "EAGAIN, read " << size << LL_ENDL;

					// Non-blocking read returned immediately.
					break;
				}
				else if(APR_STATUS_IS_EOF(status))
				{
					// This is what we normally expect when a plugin exits.
					LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL;

					if(mOwner)
					{
						mOwner->socketError(status);
					}
					result = false;
					break;
				}
				else
				{
					// some other error
					// Treat this as fatal.
					ll_apr_warn_status(status);

					if(mOwner)
					{
						mOwner->socketError(status);
					}
					result = false;
					break;
				}

				if(timeout != 0.0f)
				{
					// Second and subsequent reads should not use the timeout
					setSocketTimeout(0);
					// and should try to fill the input buffer
					request_size = sizeof(input_buf);
				}
			}
			
			processInput();
		}
	}
	
	return result;	
}
Example #10
0
bool LLPluginMessagePipe::pumpOutput()
{
	bool result = true;
	
	if(mSocket)
	{
		apr_status_t status;
		apr_size_t size;
		
		LLMutexLock lock(&mOutputMutex);
		if(!mOutput.empty())
		{
			// write any outgoing messages
			size = (apr_size_t)mOutput.size();
			
			setSocketTimeout(0);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			status = apr_socket_send(
					mSocket->getSocket(),
					(const char*)mOutput.data(),
					&size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if(status == APR_SUCCESS)
			{
				// success
				mOutput = mOutput.substr(size);
			}
			else if(APR_STATUS_IS_EAGAIN(status))
			{
				// Socket buffer is full... 
				// remove the written part from the buffer and try again later.
				mOutput = mOutput.substr(size);
			}
			else if(APR_STATUS_IS_EOF(status))
			{
				// This is what we normally expect when a plugin exits.
				llinfos << "Got EOF from plugin socket. " << llendl;

				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}
	}
	
	return result;
}
Example #11
0
static int
SendListMoviesRequest(void *data, u_size size, movie_t ***out_ptr)
{
	header_t header;
	header_t ack_header;
	void *ack_movies;
	void *to_send;
	void * ackHeader;
	int socket;
	void *header_data;
	u_size header_size;
	
	/* Tipo de pedido */
	header.opCode = __LIST_MOVIES_BY_GEN__;
	header.total_objects = 1;
	/* Identificacion del usuario */
	strcpy(header.user,log_user);
	strcpy(header.passwd,log_passwd);
	header_size = GetHeaderData(header, &header_data);	
	/* Concateno los paquetes header y pedido */
	if( (to_send = malloc(header_size+size)) == NULL )
		return CONNECT_ERROR;	
	memmove(to_send, header_data, header_size);
	free(header_data);
	/* Chequeo si realmente se manda un paquete asociado al pedido */
	
	memmove(to_send+header_size, data, size);
	
	/* Me conecto al servidor */
	if( (socket=connectTCP(server_host,server_port)) < 0 ){
		free(to_send);
		return -1;
	}
	setSocketTimeout(socket,TIMEOUT_DEFAULT);
	/* Mando el paquete */
	sendTCP(socket, to_send,header_size+size);
	free(to_send);
	if(exitPipe==1)
	{
	    exitPipe=0;
	    close(socket);
	    return TIMEOUT_ERROR;
	}
	
	/* Espero por la respuesta del servidor */
	ackHeader=receiveTCP(socket);
	if(ackHeader==NULL)
	{
	    close(socket);
	    return TIMEOUT_ERROR;
	}
	GetHeaderPack(ackHeader,&ack_header);
	fflush(stdout);
	if( ack_header.opCode == __LIST_OK__ ) {
		ack_movies = receiveTCP(socket);
		if(ack_movies==NULL)
		{
		    close(socket);
		    return TIMEOUT_ERROR;
		}
		*out_ptr = GetMovies(ack_movies,ack_header.total_objects);
		free(ack_movies);
	}
	else
		ack_header.total_objects = 0;
	close(socket);
	return ack_header.total_objects;
}
Example #12
0
static int
SendListUsersRequest(client_t ***out_ptr)
{
	header_t header;
	header_t ack_header;
	void *ack_users;
	void * ackHeader;
	int socket;
	void *header_data;
	u_size header_size;
	char * decripted;
	
	/* Tipo de pedido */
	header.opCode = __LIST_USERS__;
	header.total_objects = 1;
	/* Identificacion del usuario */
	strcpy(header.user,log_user);
	strcpy(header.passwd,log_passwd);
	header_size = GetHeaderData(header, &header_data);	
	
	/* Me conecto al servidor */
	if( (socket=connectTCP(server_host,server_port)) < 0 ){
		free(header_data);
		return -1;
	}
	setSocketTimeout(socket,TIMEOUT_DEFAULT);
	/* Mando el paquete */
	sendTCP(socket, header_data,header_size);
	free(header_data);
	if(exitPipe==1)
	{
	    exitPipe=0;
	    close(socket);
	    return -1;
	}
	
	/* Espero por la respuesta del servidor */
	ackHeader=receiveTCP(socket);
	if(ackHeader==NULL)
	{
	    close(socket);
	    return -1;
	}
	GetHeaderPack(ackHeader,&ack_header);
	
	if( ack_header.opCode == __LIST_USERS_OK__ ) {
		
		ack_users = receiveTCP(socket);
		if(ack_users==NULL)
		{
		    close(socket);
		    return -1;
		}
		decripted=Decypher(ack_users,ack_header.total_objects*(MAX_USER_LEN+MAX_USER_MAIL+MAX_USER_DESC+sizeof(unsigned char)),log_passwd);
		*out_ptr = GetUsersList(decripted,ack_header.total_objects);
		free(decripted);
		free(ack_users);
	}
	else {
		if(  ack_header.opCode == __USER_ACCESS_DENY__ || ack_header.opCode == __USER_IS_NOT_LOG__ )  
			return -2;
		else
			return -1;
	}
		
	
	close(socket);
	return ack_header.total_objects;	
	
}
Example #13
0
static int
SendListGensRequest(list_movie_request_t ***out_ptr)
{
	header_t header;
	header_t ack_header;
	void *ack_gens;
	void * dataAux;
	int socket;
	void *header_data;
	u_size header_size;
	
	/* Tipo de pedido */
	header.opCode = __LIST_GENS__;
	header.total_objects = 1;
	/* Identificacion del usuario */
	strcpy(header.user,log_user);
	strcpy(header.passwd,log_passwd);
	header_size = GetHeaderData(header, &header_data);	
	
	/* Me conecto al servidor */
	if( (socket=connectTCP(server_host,server_port)) < 0 ){
		free(header_data);
		return -1;
	}
	setSocketTimeout(socket,TIMEOUT_DEFAULT);
	/* Mando el paquete */
	sendTCP(socket, header_data,header_size);
	free(header_data);
	if(exitPipe==1)
	{
	    exitPipe=0;
	    close(socket);
	    return -1;
	}
	
	/* Espero por la respuesta del servidor */
	dataAux=receiveTCP(socket);
	if(dataAux==NULL)
	{
	    close(socket);
	    return -1;
	}
	GetHeaderPack(dataAux,&ack_header);
	
	if( ack_header.opCode == __LIST_OK__ ) {
		
		ack_gens = receiveTCP(socket);
		if(ack_gens==NULL)
		{
		    close(socket);
		    return -1;
		}
		*out_ptr = GetGenList(ack_gens,ack_header.total_objects);
		free(ack_gens);
	}
	else {
		return -1;
	}
	
	
	close(socket);
	return ack_header.total_objects;	
	
}
// DO NOT SET 'flush' TO TRUE WHEN CALLED ON THE VIEWER SIDE!
// flush is only intended for plugin-side.
bool LLPluginMessagePipe::pumpOutput(bool flush)
{
	bool result = true;
	
	if(mSocket)
	{
		apr_interval_time_t flush_time_left_usec = flush_max_block_time;
		apr_interval_time_t timeout_usec = flush ? flush_min_timeout : 0;
		
		LLMutexLock lock(&mOutputMutex);
		while(result && !mOutput.empty())
		{
			// write any outgoing messages
			apr_size_t size = (apr_size_t)mOutput.size();
			
			setSocketTimeout(timeout_usec);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			apr_status_t status = apr_socket_send(
					mSocket->getSocket(),
					(const char*)mOutput.data(),
					&size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if(status == APR_SUCCESS)
			{
				// success
				mOutput = mOutput.substr(size);
				break;
			}
			else if(APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status))
			{
				// Socket buffer is full... 
				// remove the written part from the buffer and try again later.
				mOutput = mOutput.substr(size);
				if (!flush)
					break;
				flush_time_left_usec -= timeout_usec;
				if (flush_time_left_usec <= 0)
				{
					result = false;
				}
				else if (size == 0)
				{
					// Nothing at all was written. Increment wait time.
					timeout_usec = llmin(flush_max_timeout, 2 * timeout_usec);
				}
				else
				{
					timeout_usec = llmax(flush_min_timeout, timeout_usec / 2);
				}
			}
			else if(APR_STATUS_IS_EOF(status))
			{
				// This is what we normally expect when a plugin exits.
				llinfos << "Got EOF from plugin socket. " << llendl;

				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}
	}
	
	return result;
}
Example #15
0
bool LLPluginMessagePipe::pumpOutput()
{
	bool result = true;
	
	if(mSocket)
	{
		apr_status_t status;
		apr_size_t in_size, out_size;
		
		LLMutexLock lock(&mOutputMutex);

		const char * output_data = &(mOutput.data()[mOutputStartIndex]);
		if(*output_data != '\0')
		{
			// write any outgoing messages
			in_size = (apr_size_t) (mOutput.size() - mOutputStartIndex);
			out_size = in_size;
			
			setSocketTimeout(0);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			status = apr_socket_send(mSocket->getSocket(),
									 output_data,
									 &out_size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if((status == APR_SUCCESS) || APR_STATUS_IS_EAGAIN(status))
			{
				// Success or Socket buffer is full... 
				
				// If we've pumped the entire string, clear it
				if (out_size == in_size)
				{
					mOutputStartIndex = 0;
					mOutput.clear();
				}
				else
				{
					llassert(in_size > out_size);
					
					// Remove the written part from the buffer and try again later.
					mOutputStartIndex += out_size;
				}
			}
			else if(APR_STATUS_IS_EOF(status))
			{
				// This is what we normally expect when a plugin exits.
				llinfos << "Got EOF from plugin socket. " << llendl;

				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}
	}
	
	return result;
}