/*===========================================================================* * do_pending_pipe * *===========================================================================*/ static void *do_pending_pipe(void *arg) { int r, op; struct job my_job; struct filp *f; tll_access_t locktype; my_job = *((struct job *) arg); fp = my_job.j_fp; lock_proc(fp, 1 /* force lock */); f = scratch(fp).file.filp; assert(f != NULL); scratch(fp).file.filp = NULL; locktype = (job_call_nr == READ) ? VNODE_READ : VNODE_WRITE; op = (job_call_nr == READ) ? READING : WRITING; lock_filp(f, locktype); r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes); if (r != SUSPEND) /* Do we have results to report? */ reply(fp->fp_endpoint, r); unlock_filp(f); thread_cleanup(fp); return(NULL); }
/*===========================================================================* * do_dummy * *===========================================================================*/ void *do_dummy(void *arg) { struct job my_job; int r; my_job = *((struct job *) arg); fp = my_job.j_fp; if ((r = mutex_trylock(&fp->fp_lock)) == 0) { thread_cleanup(fp); } else { /* Proc is busy, let that worker thread carry out the work */ thread_cleanup(NULL); } return(NULL); }
/*===========================================================================* * do_init_root * *===========================================================================*/ static void *do_init_root(void *arg) { struct fproc *rfp; struct job my_job; int r; char *mount_label = "fs_imgrd"; /* FIXME: obtain this from RS */ my_job = *((struct job *) arg); fp = my_job.j_fp; lock_proc(fp, 1 /* force lock */); /* This proc is busy */ lock_pm(); /* Initialize process directories. mount_fs will set them to the correct * values */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { FD_ZERO(&(rfp->fp_filp_inuse)); rfp->fp_rd = NULL; rfp->fp_wd = NULL; } receive_from = MFS_PROC_NR; if ((r = mount_fs(DEV_IMGRD, "/", MFS_PROC_NR, 0, mount_label)) != OK) panic("Failed to initialize root"); receive_from = ANY; unlock_pm(); thread_cleanup(fp); return(NULL); }
i32 core_cleanup() { socket_cleanup(); thread_cleanup(); debug_cleanup(); return RDPERROR_SUCCESS; }
bool downloadS3(const char *urlWithOptions) { if (!urlWithOptions) { return false; } int data_len = BUF_SIZE; char data_buf[BUF_SIZE]; bool ret = true; thread_setup(); GPReader *reader = reader_init(urlWithOptions); if (!reader) { return false; } do { data_len = BUF_SIZE; if (!reader_transfer_data(reader, data_buf, data_len)) { fprintf(stderr, "Failed to read data from Amazon S3\n"); ret = false; break; } fwrite(data_buf, (size_t)data_len, 1, stdout); } while (data_len && !S3QueryIsAbortInProgress()); reader_cleanup(&reader); thread_cleanup(); return ret; }
// Shut the library down. // To be called exactly once during the lifetime of the app. void bibledit_shutdown_library () { // Remove thread locks. thread_cleanup (); // Finalize SSL/TLS. filter_url_ssl_tls_finalize (); // Multiple start/stop guard. bibledit_started = false; }
/*===========================================================================* * do_dev_event * *===========================================================================*/ static void *do_dev_event(void *arg) { /* Device notifies us of an event. */ struct job my_job; my_job = *((struct job *) arg); fp = my_job.j_fp; dev_status(job_m_in.m_source); thread_cleanup(fp); return(NULL); }
/* * Export data out of GPDB. * invoked by GPDB, be careful with C++ exceptions. */ Datum s3_export(PG_FUNCTION_ARGS) { /* Must be called via the external table format manager */ if (!CALLED_AS_EXTPROTOCOL(fcinfo)) elog(ERROR, "extprotocol_import: not called by external protocol manager"); /* Get our internal description of the protocol */ GPWriter *gpwriter = (GPWriter *)EXTPROTOCOL_GET_USER_CTX(fcinfo); /* last call. destroy writer */ if (EXTPROTOCOL_IS_LAST_CALL(fcinfo)) { thread_cleanup(); if (!writer_cleanup(&gpwriter)) { ereport(ERROR, (0, errmsg("Failed to cleanup S3 extension: %s", s3extErrorMessage.c_str()))); } EXTPROTOCOL_SET_USER_CTX(fcinfo, NULL); PG_RETURN_INT32(0); } /* first call. do any desired init */ if (gpwriter == NULL) { const char *url_with_options = EXTPROTOCOL_GET_URL(fcinfo); const char *format = get_format_str(fcinfo); thread_setup(); gpwriter = writer_init(url_with_options, format); if (!gpwriter) { ereport(ERROR, (0, errmsg("Failed to init S3 extension, segid = %d, " "segnum = %d, please check your " "configurations and net connection: %s", s3ext_segid, s3ext_segnum, s3extErrorMessage.c_str()))); } EXTPROTOCOL_SET_USER_CTX(fcinfo, gpwriter); } char *data_buf = EXTPROTOCOL_GET_DATABUF(fcinfo); int32 data_len = EXTPROTOCOL_GET_DATALEN(fcinfo); if (!writer_transfer_data(gpwriter, data_buf, data_len)) { ereport(ERROR, (0, errmsg("s3_export: could not write data: %s", s3extErrorMessage.c_str()))); } PG_RETURN_INT32(data_len); }
bool uploadS3(const char *urlWithOptions, const char *fileToUpload) { if (!urlWithOptions) { return false; } size_t data_len = BUF_SIZE; char data_buf[BUF_SIZE]; size_t read_len = 0; bool ret = true; thread_setup(); GPWriter *writer = writer_init(urlWithOptions); if (!writer) { return false; } FILE *fd = fopen(fileToUpload, "r"); if (fd == NULL) { fprintf(stderr, "File does not exist\n"); ret = false; } else { do { read_len = fread(data_buf, 1, data_len, fd); if (read_len == 0) { break; } if (!writer_transfer_data(writer, data_buf, (int)read_len)) { fprintf(stderr, "Failed to write data to Amazon S3\n"); ret = false; break; } } while (read_len == data_len && !S3QueryIsAbortInProgress()); if (ferror(fd)) { ret = false; } fclose(fd); } writer_cleanup(&writer); thread_cleanup(); return ret; }
/*===========================================================================* * do_filp_gc * *===========================================================================*/ void *do_filp_gc(void *UNUSED(arg)) { struct filp *f; struct vnode *vp; for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { if (!(f->filp_state & FS_INVALIDATED)) continue; if (f->filp_mode == FILP_CLOSED || f->filp_vno == NULL) { /* File was already closed before gc could kick in */ assert(f->filp_count <= 0); f->filp_state &= ~FS_INVALIDATED; f->filp_count = 0; continue; } assert(f->filp_vno != NULL); vp = f->filp_vno; /* Synchronize with worker thread that might hold a lock on the vp */ lock_vnode(vp, VNODE_OPCL); unlock_vnode(vp); /* If garbage collection was invoked due to a failed device open * request, then common_open has already cleaned up and we have * nothing to do. */ if (!(f->filp_state & FS_INVALIDATED)) { continue; } /* If garbage collection was invoked due to a failed device close * request, the close_filp has already cleaned up and we have nothing * to do. */ if (f->filp_mode != FILP_CLOSED) { assert(f->filp_count == 0); f->filp_count = 1; /* So lock_filp and close_filp will do * their job */ lock_filp(f, VNODE_READ); close_filp(f); } f->filp_state &= ~FS_INVALIDATED; } thread_cleanup(NULL); return(NULL); }
/*===========================================================================* * do_pm * *===========================================================================*/ static void *do_pm(void *arg) { struct job my_job; struct fproc *rfp; my_job = *((struct job *) arg); rfp = fp = my_job.j_fp; lock_pm(); service_pm(); unlock_pm(); thread_cleanup(NULL); return(NULL); }
/*===========================================================================* * do_async_dev_result * *===========================================================================*/ static void *do_async_dev_result(void *arg) { endpoint_t endpt; struct job my_job; my_job = *((struct job *) arg); fp = my_job.j_fp; /* An asynchronous character driver has results for us */ if (job_call_nr == DEV_REVIVE) { endpt = job_m_in.REP_ENDPT; if (endpt == VFS_PROC_NR) endpt = find_suspended_ep(job_m_in.m_source, job_m_in.REP_IO_GRANT); if (endpt == NONE) { printf("VFS: proc with grant %d from %d not found\n", job_m_in.REP_IO_GRANT, job_m_in.m_source); } else if (job_m_in.REP_STATUS == SUSPEND) { printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n"); } else revive(endpt, job_m_in.REP_STATUS); } else if (job_call_nr == DEV_OPEN_REPL) open_reply(); else if (job_call_nr == DEV_REOPEN_REPL) reopen_reply(); else if (job_call_nr == DEV_CLOSE_REPL) close_reply(); else if (job_call_nr == DEV_SEL_REPL1) select_reply1(job_m_in.m_source, job_m_in.DEV_MINOR, job_m_in.DEV_SEL_OPS); else if (job_call_nr == DEV_SEL_REPL2) select_reply2(job_m_in.m_source, job_m_in.DEV_MINOR, job_m_in.DEV_SEL_OPS); if (deadlock_resolving) { if (fp != NULL && fp->fp_wtid == dl_worker.w_tid) deadlock_resolving = 0; } if (fp != NULL && (fp->fp_flags & FP_SYS_PROC)) { struct vmnt *vmp; if ((vmp = find_vmnt(fp->fp_endpoint)) != NULL) vmp->m_flags &= ~VMNT_CALLBACK; } thread_cleanup(NULL); return(NULL); }
/*===========================================================================* * do_control_msgs * *===========================================================================*/ static void *do_control_msgs(void *arg) { struct job my_job; my_job = *((struct job *) arg); fp = my_job.j_fp; /* Check for special control messages. */ if (job_m_in.m_source == CLOCK) { /* Alarm timer expired. Used only for select(). Check it. */ expire_timers(job_m_in.NOTIFY_TIMESTAMP); } thread_cleanup(NULL); return(NULL); }
/** * oh_ssl_finit * * Finalizes the OpenSSL library. The calls used in this routine releases global * data created/initialized by the OpenSSL library. * * Note that it is the responisbility of the caller of this function to make * sure that no other threads are making the OpenSSL library calls. The openhpid * should close all the threads and call this function from the main (single) * thread. * * Return value: None **/ void oh_ssl_finit(void) { /* TODO: Check whether any other SSL library cleanup should be called */ thread_cleanup(); ENGINE_cleanup(); CONF_modules_unload(0); ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); /* The valgrind is showing possible memory leak by * SSL_COMP_get_compression_methods() call. * * Call to SSL_free_comp_methods() may resolve the memory leak. * But not able to find this call in the openssl 0.9.8e * TODO: Find whether its a real problem or not */ }
/*===========================================================================* * do_control_msgs * *===========================================================================*/ static void *do_control_msgs(void *arg) { struct job my_job; my_job = *((struct job *) arg); fp = my_job.j_fp; /* Check for special control messages. */ if (job_m_in.m_source == CLOCK) { /* Alarm timer expired. Used only for select(). Check it. */ expire_timers(job_m_in.NOTIFY_TIMESTAMP); } else if (job_m_in.m_source == DS_PROC_NR) { /* DS notifies us of an event. */ ds_event(); } else { /* Device notifies us of an event. */ dev_status(&job_m_in); } thread_cleanup(NULL); return(NULL); }
/*===========================================================================* * do_async_dev_result * *===========================================================================*/ static void *do_async_dev_result(void *arg) { endpoint_t endpt; struct job my_job; my_job = *((struct job *) arg); fp = my_job.j_fp; /* An asynchronous character driver has results for us */ if (job_call_nr == DEV_REVIVE) { endpt = job_m_in.REP_ENDPT; if (endpt == VFS_PROC_NR) endpt = find_suspended_ep(job_m_in.m_source, job_m_in.REP_IO_GRANT); if (endpt == NONE) { printf("VFS: proc with grant %d from %d not found\n", job_m_in.REP_IO_GRANT, job_m_in.m_source); } else if (job_m_in.REP_STATUS == SUSPEND) { printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n"); } else revive(endpt, job_m_in.REP_STATUS); } else if (job_call_nr == DEV_OPEN_REPL) open_reply(); else if (job_call_nr == DEV_REOPEN_REPL) reopen_reply(); else if (job_call_nr == DEV_CLOSE_REPL) close_reply(); else if (job_call_nr == DEV_SEL_REPL1) select_reply1(job_m_in.m_source, job_m_in.DEV_MINOR, job_m_in.DEV_SEL_OPS); else if (job_call_nr == DEV_SEL_REPL2) select_reply2(job_m_in.m_source, job_m_in.DEV_MINOR, job_m_in.DEV_SEL_OPS); thread_cleanup(fp); return(NULL); }
int main(int argc, char *argv[]) { char *CApath = NULL, *CAfile = NULL; int badop = 0; int ret = 1; int client_auth = 0; int server_auth = 0; SSL_CTX *s_ctx = NULL; SSL_CTX *c_ctx = NULL; char *scert = TEST_SERVER_CERT; char *ccert = TEST_CLIENT_CERT; SSL_METHOD *ssl_method = SSLv23_method(); RAND_seed(rnd_seed, sizeof rnd_seed); if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); if (bio_stdout == NULL) bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); argc--; argv++; while (argc >= 1) { if (sgx_strcmp(*argv, "-server_auth") == 0) server_auth = 1; else if (sgx_strcmp(*argv, "-client_auth") == 0) client_auth = 1; else if (sgx_strcmp(*argv, "-reconnect") == 0) reconnect = 1; else if (sgx_strcmp(*argv, "-stats") == 0) cache_stats = 1; else if (sgx_strcmp(*argv, "-ssl3") == 0) ssl_method = SSLv3_method(); else if (sgx_strcmp(*argv, "-ssl2") == 0) ssl_method = SSLv2_method(); else if (sgx_strcmp(*argv, "-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); } else if (sgx_strcmp(*argv, "-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); } else if (sgx_strcmp(*argv, "-cert") == 0) { if (--argc < 1) goto bad; scert = *(++argv); } else if (sgx_strcmp(*argv, "-ccert") == 0) { if (--argc < 1) goto bad; ccert = *(++argv); } else if (sgx_strcmp(*argv, "-threads") == 0) { if (--argc < 1) goto bad; thread_number = atoi(*(++argv)); if (thread_number == 0) thread_number = 1; if (thread_number > MAX_THREAD_NUMBER) thread_number = MAX_THREAD_NUMBER; } else if (sgx_strcmp(*argv, "-loops") == 0) { if (--argc < 1) goto bad; number_of_loops = atoi(*(++argv)); if (number_of_loops == 0) number_of_loops = 1; } else { fprintf(stderr, "unknown option %s\n", *argv); badop = 1; break; } argc--; argv++; } if (badop) { bad: sv_usage(); goto end; } if (cipher == NULL && OPENSSL_issetugid() == 0) cipher = getenv("SSL_CIPHER"); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); c_ctx = SSL_CTX_new(ssl_method); s_ctx = SSL_CTX_new(ssl_method); if ((c_ctx == NULL) || (s_ctx == NULL)) { ERR_print_errors(bio_err); goto end; } SSL_CTX_set_session_cache_mode(s_ctx, SSL_SESS_CACHE_NO_AUTO_CLEAR | SSL_SESS_CACHE_SERVER); SSL_CTX_set_session_cache_mode(c_ctx, SSL_SESS_CACHE_NO_AUTO_CLEAR | SSL_SESS_CACHE_SERVER); if (!SSL_CTX_use_certificate_file(s_ctx, scert, SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); } else if (!SSL_CTX_use_RSAPrivateKey_file(s_ctx, scert, SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); goto end; } if (client_auth) { SSL_CTX_use_certificate_file(c_ctx, ccert, SSL_FILETYPE_PEM); SSL_CTX_use_RSAPrivateKey_file(c_ctx, ccert, SSL_FILETYPE_PEM); } if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(s_ctx)) || (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(c_ctx))) { fprintf(stderr, "SSL_load_verify_locations\n"); ERR_print_errors(bio_err); goto end; } if (client_auth) { fprintf(stderr, "client authentication\n"); SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); } if (server_auth) { fprintf(stderr, "server authentication\n"); SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER, verify_callback); } thread_setup(); do_threads(s_ctx, c_ctx); thread_cleanup(); end: if (c_ctx != NULL) { fprintf(stderr, "Client SSL_CTX stats then free it\n"); print_stats(stderr, c_ctx); SSL_CTX_free(c_ctx); } if (s_ctx != NULL) { fprintf(stderr, "Server SSL_CTX stats then free it\n"); print_stats(stderr, s_ctx); if (cache_stats) { fprintf(stderr, "-----\n"); lh_stats(SSL_CTX_sessions(s_ctx), stderr); fprintf(stderr, "-----\n"); /*- lh_node_stats(SSL_CTX_sessions(s_ctx),stderr); fprintf(stderr,"-----\n"); */ lh_node_usage_stats(SSL_CTX_sessions(s_ctx), stderr); fprintf(stderr, "-----\n"); } SSL_CTX_free(s_ctx); fprintf(stderr, "done free\n"); } exit(ret); return (0); }
void thread_start(void (*func)(void*), void*info) { func( info ); thread_cleanup( ); }
/*===========================================================================* * do_work * *===========================================================================*/ static void *do_work(void *arg) { int error; struct job my_job; my_job = *((struct job *) arg); fp = my_job.j_fp; lock_proc(fp, 0); /* This proc is busy */ if (job_call_nr == MAPDRIVER) { error = do_mapdriver(); } else if (job_call_nr == COMMON_GETSYSINFO) { error = do_getsysinfo(); } else if (IS_PFS_VFS_RQ(job_call_nr)) { if (who_e != PFS_PROC_NR) { printf("VFS: only PFS is allowed to make nested VFS calls\n"); error = ENOSYS; } else if (job_call_nr <= PFS_BASE || job_call_nr >= PFS_BASE + PFS_NREQS) { error = ENOSYS; } else { job_call_nr -= PFS_BASE; error = (*pfs_call_vec[job_call_nr])(); } } else { /* We're dealing with a POSIX system call from a normal * process. Call the internal function that does the work. */ if (job_call_nr < 0 || job_call_nr >= NCALLS) { error = ENOSYS; } else if (fp->fp_pid == PID_FREE) { /* Process vanished before we were able to handle request. * Replying has no use. Just drop it. */ error = SUSPEND; } else { #if ENABLE_SYSCALL_STATS calls_stats[job_call_nr]++; #endif error = (*call_vec[job_call_nr])(); } } /* Copy the results back to the user and send reply. */ if (error != SUSPEND) { if ((fp->fp_flags & FP_SYS_PROC)) { struct vmnt *vmp; if ((vmp = find_vmnt(fp->fp_endpoint)) != NULL) vmp->m_flags &= ~VMNT_CALLBACK; } if (deadlock_resolving) { if (fp->fp_wtid == dl_worker.w_tid) deadlock_resolving = 0; } reply(fp->fp_endpoint, error); } thread_cleanup(fp); return(NULL); }
bool HitTestEngine::start() { // don't know if we even need this any more #ifdef _MSC_VER thread_setup(); #endif // if it's a single request type, we need to create a temp Script object // to pass to the threads, then delete it later on if (m_hitTestType == HIT_REQUEST) { if (!m_pRequest) // shouldn't happen, but... { return false; } m_pScript = new Script(m_pRequest); } // copy script over, so load test results saver knows about each step if (m_pSaver && m_pScript) { m_pSaver->copyScript(*m_pScript); } std::vector<HitLoadRequestThread *> aThreads; int threadCount = 0; for (int i = 0; i < m_numberOfThreads; i++) { RequestThreadData *data = new RequestThreadData(i + 1, m_pScript, m_pSaver, m_repeats); HitLoadRequestThread *newThread = new HitLoadRequestThread(data); if (newThread) { threadCount++; aThreads.push_back(newThread); } } printf("Created %i threads...\n", threadCount); std::vector<HitLoadRequestThread *>::iterator it = aThreads.begin(); for (; it != aThreads.end(); ++it) { (*it)->start(); } for (it = aThreads.begin(); it != aThreads.end(); ++it) { (*it)->waitForCompletion(); delete *it; } if (m_hitTestType == HIT_REQUEST && m_pScript) { delete m_pScript; } printf("All threads finished.\n"); #ifdef _MSC_VER thread_cleanup(); #endif return true; }
void deinit_ssl(void) { thread_cleanup(); }
/* * Import data into GPDB. * invoked by GPDB, be careful with C++ exceptions. */ Datum s3_import(PG_FUNCTION_ARGS) { S3ExtBase *myData; char *data; int data_len; size_t nread = 0; /* Must be called via the external table format manager */ if (!CALLED_AS_EXTPROTOCOL(fcinfo)) elog(ERROR, "extprotocol_import: not called by external protocol manager"); /* Get our internal description of the protocol */ myData = (S3ExtBase *)EXTPROTOCOL_GET_USER_CTX(fcinfo); if (EXTPROTOCOL_IS_LAST_CALL(fcinfo)) { if (myData) { thread_cleanup(); if (!myData->Destroy()) { ereport(ERROR, (0, errmsg("Failed to cleanup S3 extention"))); } delete myData; } /* * Cleanup function for the XML library. */ xmlCleanupParser(); PG_RETURN_INT32(0); } if (myData == NULL) { /* first call. do any desired init */ curl_global_init(CURL_GLOBAL_ALL); thread_setup(); const char *p_name = "s3"; char *url_with_options = EXTPROTOCOL_GET_URL(fcinfo); char *url = truncate_options(url_with_options); char *config_path = get_opt_s3(url_with_options, "config"); if (!config_path) { // no config path in url, use default value // data_folder/gpseg0/s3/s3.conf config_path = strdup("s3/s3.conf"); } bool result = InitConfig(config_path, ""); if (!result) { free(config_path); ereport(ERROR, (0, errmsg("Can't find config file, please check"))); } else { ClearConfig(); free(config_path); } InitLog(); if (s3ext_accessid == "") { ereport(ERROR, (0, errmsg("ERROR: access id is empty"))); } if (s3ext_secret == "") { ereport(ERROR, (0, errmsg("ERROR: secret is empty"))); } if ((s3ext_segnum == -1) || (s3ext_segid == -1)) { ereport(ERROR, (0, errmsg("ERROR: segment id is invalid"))); } myData = CreateExtWrapper(url); if (!myData || !myData->Init(s3ext_segid, s3ext_segnum, s3ext_chunksize)) { if (myData) delete myData; ereport(ERROR, (0, errmsg("Failed to init S3 extension, segid = " "%d, segnum = %d, please check your " "configurations and net connection", s3ext_segid, s3ext_segnum))); } EXTPROTOCOL_SET_USER_CTX(fcinfo, myData); free(url); } /* ======================================================================= * DO THE IMPORT * ======================================================================= */ data = EXTPROTOCOL_GET_DATABUF(fcinfo); data_len = EXTPROTOCOL_GET_DATALEN(fcinfo); uint64_t readlen = 0; if (data_len > 0) { readlen = data_len; if (!myData->TransferData(data, readlen)) ereport(ERROR, (0, errmsg("s3_import: could not read data"))); nread = (size_t)readlen; // S3DEBUG("read %d data from S3", nread); } PG_RETURN_INT32((int)nread); }
int main(int argc, char **argv) { u_short server_port = 5500; u_short viewer_port = 5900; int max_slots = 50; char * dump_file = NULL; thread_t hServerThread; thread_t hViewerThread; /* Arguments */ if (argc > 1) { for(int i = 1; i < argc; i++) { if( _stricmp( argv[i], "-server" ) == 0 ) { /* Requires argument */ if( (i+i) == argc ) { usage( argv[0] ); return 1; } server_port = atoi( argv[(i+1)] ); if( argv[(i+1)][0] == '-' ) { usage( argv[0] ); return 1; } else if( server_port == 0 ) { usage( argv[0] ); return 1; } else if( server_port > 65535 ) { usage( argv[0] ); return 1; } i++; } else if( _stricmp( argv[i], "-viewer" ) == 0 ) { /* Requires argument */ if( (i+i) == argc ) { usage( argv[0] ); return 1; } viewer_port = atoi( argv[(i+1)] ); if( argv[(i+1)][0] == '-' ) { usage( argv[0] ); return 1; } else if( viewer_port == 0 ) { usage( argv[0] ); return 1; } else if( viewer_port > 65535 ) { usage( argv[0] ); return 1; } i++; } else if ( _stricmp( argv[i], "-dump" ) == 0 ) { if( (i+i) == argc ) { usage( argv[0] ); return 1; } dump_file = argv[(i+1)]; i++; } else if ( _stricmp( argv[i], "-loglevel" ) == 0 ) { if( (i+i) == argc ) { usage( argv[0] ); return 1; } char level = ::get_log_level(argv[(i+1)]); if(level == -1) { usage( argv[0] ); return 1; } ::logger_level = level; i++; } else if ( _stricmp( argv[i], "-iobuffer_size" ) == 0 ) { if( (i+i) == argc ) { usage( argv[0] ); return 1; } int buffer_sz = atoi(argv[(i+1)]); if(buffer_sz <= 128) { usage( argv[0] ); return 1; } IOBUFFER_SIZE = buffer_sz; i++; } else if ( _stricmp( argv[i], "-max_slots" ) == 0 ) { if( (i+i) == argc ) { usage( argv[0] ); return 1; } int _max_slots = atoi(argv[(i+1)]); if(_max_slots < 1) { usage( argv[0] ); return 1; } max_slots = _max_slots; i++; } else { usage( argv[0] ); return 1; } } } #ifdef WIN32 /* Winsock */ if( WinsockInitialize() == 0 ) return 1; #endif /* Start */ logp(ERROR, "VNC Repeater [Version %s]", VNCREPEATER_VERSION); log(INFO, "Copyright (C) 2010 Juan Pedro Gonzalez Gutierrez. Licensed under GPL v2."); log(INFO, "Copyright (C) 2013 XSoft Ltd. - Andrey Andreev - www.xsoftbg.com. Licensed under GPL v2."); log(INFO, "Get the latest version at http://code.google.com/p/vncrepeater/ or https://github.com/XSoftBG/repeater\n"); /* Initialize some variables */ notstopped = true; InitializeSlots(max_slots); /* Trap signal in order to exit cleanlly */ signal(SIGINT, ExitRepeater); listener_thread_params * server_thread_params = (listener_thread_params *)malloc(sizeof(listener_thread_params)); memset(server_thread_params, 0, sizeof(listener_thread_params)); listener_thread_params * viewer_thread_params = (listener_thread_params *)malloc(sizeof(listener_thread_params)); memset(viewer_thread_params, 0, sizeof(listener_thread_params)); server_thread_params->port = server_port; viewer_thread_params->port = viewer_port; // Start multithreading... // Tying new threads ;) if (notstopped) { if ( thread_create(&hServerThread, NULL, server_listen, (LPVOID)server_thread_params) != 0 ) { log(FATAL, "Unable to create the thread to listen for servers."); notstopped = false; } } if (notstopped) { if ( thread_create(&hViewerThread, NULL, viewer_listen, (LPVOID)viewer_thread_params) != 0 ) { log(FATAL, "Unable to create the thread to listen for viewers."); notstopped = false; } } if (notstopped) { FILE *f = fopen( "pid.repeater", "w" ); if(!f) perror("pid.repeater"), exit(1); fprintf(f, "%d\n", (int)getpid()); fclose(f); } // Main loop while (notstopped) { /* Clean slots: Free slots where the endpoint has disconnected */ CleanupSlots(); if (dump_file != NULL) { int dump_fd = ::open(dump_file, O_CREAT | O_TRUNC | O_WRONLY, 0644); std::string json = DumpSlots(); if (!json.empty()) write (dump_fd, json.c_str(), json.length() ); close (dump_fd); } /* Take a "nap" so CPU usage doesn't go up. */ #ifdef WIN32 Sleep(5000000); #else usleep(5000000); #endif } log(ERROR, "\nExiting VNC Repeater...\n"); notstopped = false; /* Free the repeater slots */ FreeSlots(); /* Close the sockets used for the listeners */ socket_close( server_thread_params->sock ); socket_close( viewer_thread_params->sock ); /* Free allocated memory for the thread parameters */ free( server_thread_params ); free( viewer_thread_params ); /* Make sure the threads have finalized */ if (thread_cleanup(hServerThread, 30) != 0) log(ERROR, "The server listener thread doesn't seem to exit cleanlly."); if (thread_cleanup(hViewerThread, 30) != 0) log(ERROR, "The viewer listener thread doesn't seem to exit cleanlly."); FinalizeSlots(); #ifdef WIN32 WinsockFinalize(); // Cleanup Winsock. #endif return 0; }