/* 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; }
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; }
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; }
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; }
/*----------------------------------------------------------------------------*/ 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; }
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; }
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; }
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; }
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; }
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; }
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; }