Пример #1
0
/* -------------------------------------------------------------------------- *
 * Hauptfunktion des Clients                                                  *
 * -------------------------------------------------------------------------- */
int client_main(int argc, char *argv[])
{
  client_init();
  client_run();
  client_shutdown();
  
  return 0;
}
Пример #2
0
static void sig_handler(int sig_num) 
{
    // fprintf(stderr, "Captured interruption, quit..\n");
    if ( rtt.mode )
	print_ping_result();
    client_shutdown();
    exit(sig_num);
}
Пример #3
0
bool NetworkLayerENet::client_restart()
{
    client_shutdown();

    // no bind
    // two connections (lobby server and game host)
    // two channels (a reliable and an unreliable)
    // no up/down speed limit
    local_client = enet_host_create(NULL, 2, 2, 0, 0);
    if (!local_client) {
        fprintf(stderr, "[error][net] Could not open client connection port.\n");
        return false;
    }
    return true;
}
Пример #4
0
void client_libc_error(const char *fmt, ...)
{
	char *msg;
	
	va_list ap;
	
	va_start(ap, fmt);
	vasprintf(&msg, fmt, ap);
	va_end(ap);

	console_print("Error: %s; %s.\n", msg, strerror(errno));
	
	free(msg);
	
	client_shutdown();
}
Пример #5
0
void main_thread()
{
	struct pollfd *fds;
	int fdcount;
	
	fdcount = 5;
	
	fds = calloc(sizeof(struct pollfd), fdcount);
	
	fds[0].fd = x_render_pipe[0];		fds[0].events = POLLIN;
	fds[1].fd = console_pipe[0];		fds[1].events = POLLIN;
	fds[2].fd = key_out_pipe[0];		fds[2].events = POLLIN;
	fds[3].fd = download_out_pipe[0];	fds[3].events = POLLIN;
	fds[4].fd = net_out_pipe[0];	fds[4].events = POLLIN;
	

	while(1)
	{
		if(downloading_map)
			fdcount = 4;
		else
			fdcount = 5;
		
		if(TEMP_FAILURE_RETRY(poll(fds, fdcount, -1)) == -1)
			client_shutdown();
		
		if(fds[0].revents & POLLIN)
			process_x_render_pipe();
		
		if(fds[1].revents & POLLIN)
			process_console_pipe();
		
		if(fds[2].revents & POLLIN)
			process_key_out_pipe();
		
		if(fds[3].revents & POLLIN)
			process_download_out_pipe();
		
		if(!downloading_map)
		{
			if(fds[4].revents & POLLIN)
				process_network();
		}
	}
}
Пример #6
0
static bool	check_fd_set(t_sockpool *pool, t_sockpool_node *node,
			     fd_set *fds, int (*action)(t_sockpool_node *))
{
  int		rc;

  if (FD_ISSET(node->socket, fds))
    {
      --pool->nbset;
      if ((rc = action(node)) <= 0)
	{
	  if (rc == -1)
	    print_perror("network I/O error");
	  client_shutdown(node);
	  return (false);
	}
    }
  return (true);
}
Пример #7
0
/* -------------------------------------------------------------------------- *
 * Schreibt einen Log-Eintrag auf die Konsole oder auf stderr                 *
 * -------------------------------------------------------------------------- */
void client_write(int mod, int lev, const char *s, ...)
{
  char    msg[4096];
  va_list args;
  size_t  n = 0;
  
  if(lev > LOGLEVEL)
    return;
  
  va_start(args, s);
  
  strncpy(&msg[n], client_symbols[mod], sizeof(msg) - n);
  n += 3;
  msg[n++] = ' ';
  
#if defined(DEBUG) && defined(DEBUG_TICKS)
  {
    uint32_t ticks = (client_subsystems ? SDL_GetTicks() : 0);
    sprintf(&msg[n], "(%04u.%03u)", (ticks / 1000) % 10000, ticks % 1000);
    n += 10;
    msg[n++] = ' ';
  }
#endif
  
  strncpy(&msg[n], client_modules[mod], sizeof(msg) - n);
  n += strlen(&msg[n]);
  msg[n++] = ':';
  msg[n++] = ' ';
  
  vsnprintf(&msg[n], sizeof(msg) - n, s, args);
  
  /* Auf die aktive Konsole damit */
  if(lev <= CONSOLE)
    client_puts("%s", &msg[n]);
  
  if(lev != CONSOLE)
    fprintf(stderr, "%s\n", msg);
  
  va_end(args);
  
  if(lev == ERROR)
    client_shutdown();
}
Пример #8
0
int main(int argc, char **argv)
{
	client_t client;
	int cmd, err = 0;
	cmd = parseopts(argc, argv, &client);
	if (cmd < 0)
		return 1;
	/* call function for command */
	switch (cmd) {
	case 1:
		err = do_bind(&client);
		break;
	case 2:
		err = do_unbind(&client);
		break;
	case 3:
		err = do_setcache(&client);
		break;
	}

	client_shutdown(&client);
	return err;
}
int main(int argc, char *argv[])
{
    struct pj_getopt_option long_options[] = {
	{ "realm",	1, 0, 'r'},
	{ "username",	1, 0, 'u'},
	{ "password",	1, 0, 'p'},
	{ "fingerprint",0, 0, 'F'},
	{ "tcp",        0, 0, 'T'},
	{ "help",	0, 0, 'h'},
	{ "stun-srv",   1, 0, 'S'},
	{ "nameserver", 1, 0, 'N'}
    };
    int c, opt_id;
    char *pos;
    pj_status_t status;

    while((c=pj_getopt_long(argc,argv, "r:u:p:S:N:hFT", long_options, &opt_id))!=-1) {
	switch (c) {
	case 'r':
	    o.realm = pj_optarg;
	    break;
	case 'u':
	    o.user_name = pj_optarg;
	    break;
	case 'p':
	    o.password = pj_optarg;
	    break;
	case 'h':
	    usage();
	    return 0;
	case 'F':
	    o.use_fingerprint = PJ_TRUE;
	    break;
	case 'T':
	    o.use_tcp = PJ_TRUE;
	    break;
	case 'S':
	    o.stun_server = pj_optarg;
	    break;
	case 'N':
	    o.nameserver = pj_optarg;
	    break;
	default:
	    printf("Argument \"%s\" is not valid. Use -h to see help",
		   argv[pj_optind]);
	    return 1;
	}
    }

    if (pj_optind == argc) {
	puts("Error: TARGET is needed");
	usage();
	return 1;
    }

    if ((pos=pj_ansi_strchr(argv[pj_optind], ':')) != NULL) {
	o.srv_addr = argv[pj_optind];
	*pos = '\0';
	o.srv_port = pos+1;
    } else {
	o.srv_addr = argv[pj_optind];
    }

    if ((status=init()) != 0)
	goto on_return;
    
    //if ((status=create_relay()) != 0)
    //	goto on_return;
    
    console_main();

on_return:
    client_shutdown();
    return status ? 1 : 0;
}
Пример #10
0
void NetworkLayerENet::cleanup()
{
    gamehost_shutdown();
    client_shutdown();
    enet_deinitialize();
}
Пример #11
0
static void 
sighand(int s)
{
	client_shutdown();
}
Пример #12
0
/* -------------------------------------------------------------------------- *
 * Setzt den Videomodus                                                       *
 * -------------------------------------------------------------------------- */
void client_setmode(void)
{
  SDL_Rect real_rect;
  SDL_Rect *best_rect;
  SDL_Surface *bg;
  
  if(client_config.fullscreen)    
  {
    /* Im Vollbildmodus schauen wir welcher Hardware-Modus am passendsten ist */
    if((best_rect = client_bestmode(client_config.width, client_config.height)))
      real_rect = *best_rect;
    else
      real_rect = *client_videomodes[0];
    
    client_rect.w = client_config.width;
    client_rect.h = client_config.height;
    
    sgAlignRect(&real_rect, &client_rect, SG_ALIGN_LEFT|SG_ALIGN_TOP);
  }
  else
  {
    real_rect.x = 0;
    real_rect.y = 0;
    real_rect.w = client_config.width;
    real_rect.h = client_config.height;
    
    client_rect = real_rect;
  }
  
  /* Videomodus setzen */
  client_screen = 
    SDL_SetVideoMode(real_rect.w, real_rect.h, client_config.depth,
                     SDL_HWSURFACE|(client_config.fullscreen ? SDL_FULLSCREEN : 0));

  SDL_SetClipRect(client_screen, &client_rect);
  
  if(client_screen == NULL)
  {
    client_log(ERROR, "Kann Videomodus nicht setzen!");
    client_shutdown();
  }
  
  /* Hintergrund gleich sofort anzeigen */
  if((bg = client_render()))
  {
    SDL_BlitSurface(bg, NULL, client_screen, NULL);
    SDL_FreeSurface(bg);
    client_flip();
  }
  
  client_log(STATUS, "Video-Modus %ux%u @ %ubpp%s",
             client_screen->w, client_screen->h,
             client_screen->format->BitsPerPixel,
             (client_screen->flags & (SDL_HWSURFACE|SDL_HWACCEL)) ?
             " (Hardwarebeschleunigt)" : "");

  client_debug(INFO, "Hardware R-Maske %08x", client_screen->format->Rmask);
  client_debug(INFO, "Hardware G-Maske %08x", client_screen->format->Gmask);
  client_debug(INFO, "Hardware B-Maske %08x", client_screen->format->Bmask);
  client_debug(INFO, "Client R-Maske %08x", RMASK);
  client_debug(INFO, "Client G-Maske %08x", GMASK);
  client_debug(INFO, "Client B-Maske %08x", BMASK);  
  
  /* Bildschirm-Rechteck des ganzen Clients */
/*  client_rect.x = client_rect.y = 0;

  client_rect.w = client_screen->w;
  client_rect.h = client_screen->h;*/
}
Пример #13
0
static void udp_ping() 
{
    char buff[BUFLEN];
    int i, iteration; 
    double rttTime;
 
    iteration = 2; // start from a small size
    rtt.mode = 1;

    udpsock.elapsedTime = 0;
    
    /******** Obtain the iteration number for a minimum test time **********/
    /******** Double the iteration for at most 20 times (2^20=2M) **********/
    
    for ( i = 1; udpsock.elapsedTime < MINITIME && i < 20; i++ ) {
	
	/* There is a synchronization step for UDP-ping, so the iteration for
	 * server is one more than local's (iteration+1)
	 */
	
	sprintf(buff, test_start_str, udpsock.dataSize, iteration+1);	
	if ( tcp_send_request(buff, strlen(buff), &tcpsock) == NOTOK ) {
	    perror("Failed to send request to server.");
	    client_shutdown();
	    exit (1);
	}
	
	/********************* Start estimation test  *********************/
	
	if ( client_udp_ping (iteration, &udpsock) == OK ) {
	    iteration *= 2;
	} else if ( error == TIMEOUT || error == DISORDER ) {

	    fprintf(stderr, "Ping error: %s\n", (error == TIMEOUT) ? 
		    "Packet lost":"Packet disorder");
	  
	    /************ An estra synchronization step ********************/ 
	    sprintf(buff, test_sync_str);	
	    if ( tcp_send_request(buff, strlen(buff), &tcpsock) == NOTOK ) {
		perror("Failed to send request to server.");
		client_shutdown();
		exit (1);
	    } else if ( tcp_get_request(buff, &tcpsock) == NOTOK || 
		 strncmp(buff, test_sync_str, 20) != 0 ) {
		perror("Failed to synchronize.");
		exit (1);
	    }    
	    continue;

	} else {
	    perror("UDP communication error.");
	    exit (1);
	}
    } 

    if ( i == 20 ) { // Too many trials and 
	perror("UDP ping pre-test error.");
	exit (1);
    }
    
    if ( setting.verbose ) {
	fprintf(stderr, "RTT (latency) test\n%s <--> %s\n", localhost, hostname);
	fprintf(stderr, "UDP-port: %d UDP-buffer: %d\nMessage-size: %d Iteration: %d\n", 
		udpsock.port, udpsock.sendBuf, rtt.size, iteration);
    }

    if ( setting.writeOption ) {
	get_local_time(buff, BUFLEN);
	fprintf(output, "# UDP roundtrip time test %s\n", buff);
	fprintf(output, "# %s <--> %s\n", localhost, hostname);
	fprintf(output, "# UDP-send-buffer: %d UDP-recv-buffer: %d\n", 
		udpsock.sendBuf, udpsock.recvBuf);
	fprintf(output, "# Message-size: %d Iteration: %d\n", rtt.size, iteration);
    }
    
    /***************** Endless loop of RTT (latency) test **************/
    
    for( i = 1; i <= setting.repeat; i++) {
	
	/* There is a synchronization step for UDP-ping, so the iteration for
	 * server is one more than local's (iteration+1)
	 */

	sprintf(buff, test_start_str, udpsock.dataSize, iteration+1);
	if ( tcp_send_request(buff, strlen(buff), &tcpsock) == NOTOK ) { 
	    perror("Failed to send request to server.");
	    client_shutdown();
	    exit (1);
	}

	if ( client_udp_ping (iteration, &udpsock) == NOTOK ) {
	    if ( error == TIMEOUT ) {
		fprintf(stderr, "UDP Round Trip Time (%d) : Packet lost\n", i);
		if ( setting.writeOption ) 
		    fprintf(output, "UDP Round Trip Time (%d) : Packet lost\n", i);
	    } else if ( error == DISORDER ) {
		fprintf(stderr, "UDP Round Trip Time (%d) : Packet disordered\n", i);
		if ( setting.writeOption ) 
		    fprintf(output, "UDP Round Trip Time (%d) : Packet disordered\n", i);
	    } else {
		perror("UDP communication error.");
		exit(1);
	    }
	    rtt.trial++;
	    rtt.loss++;

	    /************ Need a synchronization for this case *************/

	    sprintf(buff, test_sync_str);	
	    if ( tcp_send_request(buff, strlen(buff), &tcpsock) == NOTOK ) {
		perror("Failed to send request to server(sync).");
		client_shutdown();
		exit (1);
	    } else if ( tcp_get_request(buff, &tcpsock) == NOTOK || 
		 strncmp(buff, test_sync_str, 20) != 0 ) {
		perror("Failed to synchronize.");
		exit (1);
	    } 
   
	} else {  // UDP ping OK

	    /******** Compute the RTT times and their statistics *******/
	    
	    rttTime = udpsock.elapsedTime*1.0/iteration;
	    rtt.trial++;
	    rtt.sum += rttTime;
	    rtt.avg = rtt.sum/rtt.trial;
	    if ( rtt.min > rttTime)
		rtt.min = rttTime;
	    if ( rtt.max < rttTime)
		rtt.max = rttTime;
	    if ( rttTime > 1000 ) {
		fprintf(stderr, "UDP Round Trip Time (%d) : %6.3f msec\n", i, rttTime/1000);
		if ( setting.writeOption ) 
		    fprintf(output, "UDP Round Trip Time (%d) : %6.3f msec\n", i, rttTime/1000);
	    } else {
		fprintf(stderr, "UDP Round Trip Time (%d) : %6.3f usec\n", i, rttTime);
		if ( setting.writeOption ) 
		    fprintf(output, "UDP Round Trip Time (%d) : %6.3f usec\n", i, rttTime);
	    }
	}	    
	sleep (1);
    }
    
    return;
}
Пример #14
0
int main(int argc, char *argv[]) 
{
    char buff[BUFLEN], sysbuff[2*BUFLEN];         
    short * ptr;                                  
    int i;                                        
    int testMode;                                 // Test mode (RTT/througput)
    int lossPackets;                              // Lost packet number
    long_int * s_rtime_usec;                      // Server process wall clock time 
    long_int * s_utime_usec;                      // Server process time in user mode
    long_int * s_stime_usec;                      // Server process time in system mode
    double clientTP, serverTP;                    // client/server throughputs
    double lossRate;                              // Packet loss rate
    struct SYSInfo * sysinfo = NULL;              // System (CPU/Interrupts) information
    struct SYSInfo * serverinfo = NULL;           // Server's system information
    struct PROInfo * proinfo;                     // Process information
    struct timeval tv;                            // Timestamp
    double ts;

    /**************** At least given server name ***************************/

    if ( argc > 1 && strcmp(argv[1], "--help")==0 ) {
	fprintf(stderr, help_description);
	fprintf(stderr, help_usage,  DEFAULTPORT, DEFAULTDATAGRAM, DEFAULTSIZE, 
		DEFAULTPORT, DEFAULTREPEAT, DEFAULTTIME);
	fprintf(stderr, help_example);
	return 0;
    } else if ( argc < 3 ) {
	print_usage();
	return 1;
    }

    /********* Data initialization and parse the command line **************/
    
    init_data();
    parse_command(argc, argv, &testMode);

    /********* Just send data in case of UDP traffic generator *************/
    
    if ( setting.udpGen ) {
	udp_traffic_generator(hostname, tcpsock.port, udpsock.sendBuf,
			      setting.testTime, setting.throughput);
	return 0;
    }

    /******************** Check the write file option **********************/

    if ( setting.writeOption ) {
	if ( (output = fopen(filename, "w")) == NULL ) {
	    fprintf(stderr, "%s: Unable to write the file!\n", filename);
	    setting.writeOption = 0;
	}
    } 

    /*************** Allocate memory to hold CPU information ***************/
    
    if ( setting.CPUoption ) { 

	/** Two more items to hold the syslog of pre/post states of test ***/

	if ( (sysinfo = (struct SYSInfo *)malloc((setting.repeat + 2) 
			* sizeof(struct SYSInfo))) == NULL ) {
	    perror("Failed to malloc.");
	    exit(1);
	}

	if ( start_trace_system( &sysinfo[0]) == NOTOK ) {
	    fprintf(stderr, "Failed to monitor system information.\n");
	    setting.CPUoption = 0;
	} else {
	    sleep(1);
	    stop_trace_system( &sysinfo[0] );
	}
    }
 
    /***********************  TCP connection to server *********************/

    if (client_tcp_connect(hostname, &tcpsock) == NOTOK) {
	fprintf(stderr, "%s : %d ", hostname, tcpsock.port);
	perror("Unable to establish TCP connection.");
	return 1;
    }

    /*************** Send parameters to server *****************************/
    
    sprintf(buff, test_init_str, testMode, udpsock.tos, setting.CPUoption, 
	    server.sendBuf, server.recvBuf, udpsock.packetSize, udpsock.dataSize);
    if ( tcp_send_request(buff, strlen(buff), &tcpsock) == NOTOK ) {
	perror("TCP send parameters error.");
	return 1;
    }
 
    /************  Get server's UDP connection setting *********************/

    if ( tcp_get_request(buff, &tcpsock) == NOTOK || 
	 sscanf(buff, server_setting_str, &udpsock.port, &server.tos, 
		&setting.sCPUoption, &server.sendBuf, &server.recvBuf, 
		&server.packetSize, &server.dataSize) != 7) {
	perror("Failed to get UDP connection information.");
	return 1;
    }    

    /************ Initialization of UDP communication  *********************/

    if (client_udp_init(hostname, &udpsock) == NOTOK) {
	fprintf(stderr, "%s : %d ", hostname, udpsock.port);
	perror("Failed to establish the UDP connection.");
	return 1;
    }

    if ( gethostname(localhost, BUFLEN) < 0 ) {
	perror("gethostname.");
	strcpy(localhost, "Localhost");
    }

    /************************* Allocate memory *****************************/

    if ( (buffer = (char *) malloc ( udpsock.packetSize)) == NULL ){
	fprintf(stderr, "Malloc error : %d\n", udpsock.packetSize);
        return 1;
    }

    /******* Randomize the buffer to prevent the possible compression ******/
    
    srand(time(NULL));
    for(ptr = (short *)buffer; ptr < (short *)(buffer+udpsock.packetSize); ptr += 2 )
	*ptr = (short)rand();

    /*** Allocate memory to store the client/server process information ****/
	
    if ( (proinfo = (struct PROInfo *)malloc((setting.repeat)*sizeof(struct PROInfo))) == NULL ||
	 (s_rtime_usec = (long_int *)malloc((setting.repeat)*sizeof(long_int))) == NULL ||
	 (s_utime_usec = (long_int *)malloc((setting.repeat)*sizeof(long_int))) == NULL ||
	 (s_stime_usec = (long_int *)malloc((setting.repeat)*sizeof(long_int))) == NULL ) {
	perror("Failed to malloc.");
	exit(1);
    }
    
#ifdef DEBUG
    fprintf(stderr, " DEBUG: Client connected to server on port: %d\n", udpsock.port);
#endif

    /********************** Handle the interruption ************************/

    signal(SIGINT, sig_handler);
    signal(SIGTSTP, sig_handler);

    /********************** RTT (latency test) *****************************/

    if ( testMode == LATENCY ) {
	udp_ping();
	print_ping_result();
	return 0;
    }

    /************************ UDP throughput test **************************/

    /** We need another container to hold server's system info if defined **/

    if ( setting.sCPUoption ) { // Server also monitor the system resource
	if ( (serverinfo = (struct SYSInfo *)malloc((setting.repeat + 2) 
			   * sizeof(struct SYSInfo))) == NULL ) {
	    perror("Failed to malloc.");
	    exit(1);
	}
	bzero(buff, BUFLEN);
	if ( tcp_get_request(sysbuff, &tcpsock) == NOTOK ||
	     string_to_sysinfo( &serverinfo[0], sysbuff, 2*BUFLEN) == NOTOK ) {
	    perror("Failed to get server's initial system information.");
	    exit (1);
	}
    }

    /******************** Print out the connection message *****************/

    if ( setting.verbose ) {
	fprintf(stderr, "UDP throughput %s test\n%s (client) <--> %s (server)\n", 
		setting.exponential ? "exponential" : "fixed packet size", localhost, hostname);
	fprintf(stderr, "UDP-port: %d UDP-send-buffer: %d UDP-recv-buffer: %d\n",
		udpsock.port, udpsock.sendBuf, udpsock.recvBuf);
    }

    /******************* Write test parameters to a file *******************/

    if ( setting.writeOption ) {

	get_local_time(curtime, BUFLEN);
	fprintf(output, "# UDP communication test -- %s\n", curtime);
	fprintf(output, "# %s size %s stream test\n", setting.exponential ? 
		"Exponential":"Fixed packet", setting.bidirection ? "bidirectional":"unidirectional");
	fprintf(output, "# Hosts: %s (client) <--> %s (server)\n\n", localhost, hostname);
	fprintf(output, "# Client UDP socket buffer size (Bytes) -- SNDBUF: %d RCVBUF: %d\n", 
		udpsock.sendBuf, udpsock.recvBuf );
	fprintf(output, "# Server UDP socket buffer size (Bytes) -- SNDBUF: %d RCVBUF: %d\n", 
		server.sendBuf, server.recvBuf);
	qos_type(&udpsock, buff);
	fprintf(output, "# Client IP TOS type: %s\n", buff);
	qos_type(&server, buff);
	fprintf(output, "# Server IP TOS type: %s\n", buff);
	fprintf(output, "# UDP datagram (packet) size (Bytes) -- Client: %d Server: %d\n", udpsock.packetSize, server.packetSize);

	if ( setting.exponential ) {  // Exponential test
	    fprintf(output, "# Test time (second): %f\n\n", setting.testTime);
	    if ( !setting.bidirection ) { 
		fprintf(output, "#   Size    Network     Local    Client      Client    Server      Server    Server  ServerRecv\n");
		fprintf(output, "#  (Byte)    (Mbps)    (Mbps)   SentPkg    SentByte   RecvPkg    RecvByte   LostPkg    LossRate  Timestamp\n");
	    } else {
		fprintf(output, "#   Size    Network     Local    Client      Client    Server      Server    Client      Client    Server      Server  ServerRecv\n");
		fprintf(output, "#  (Byte)    (Mbps)    (Mbps)   SentPkg    SentByte   RecvPkg    RecvByte   RecvPkg    RecvByte   SentPkg    SentByte    LossRate  Timestamp\n");
	    }
	}
	else { // Fixed packet size test
	    fprintf(output, "# Data size of each read/write (Bytes) -- Client: %d Server: %d\n", udpsock.dataSize, server.dataSize); 
	    fprintf(output, "# Message size (Bytes): %lld\n", setting.messageSize);
	    fprintf(output, "# Test time (Second): %f\n# Test repeat: %d\n\n", setting.testTime, setting.repeat); 

	    if ( ! setting.bidirection ) // One way unidirectional test
		fprintf(output, "#   Network(Mbps) Local(Mbps) SentPkg(C) SentByte(C) RecvPkg(S) RecvByte(S)  LostPkg  LossRate Timestamp\n");
	    else { // bidirection test 
		fprintf(output, "#     Network     Local    Client     Client    Server     Server    Client     Client    Server     Server   Server\n");
		fprintf(output, "#   throughput throughput   sent       sent      recv       recv      recv       recv      sent       sent     recv     Timestamp\n");
		fprintf(output, "#     (Mbps)     (Mbps)    packet      byte     packet      byte     packet      byte     packet      byte   loss-rate\n");
	    } // bidriection test
	} // Fixed packet size test

    } // If write option

    /********************** Start UDP throughput test **********************/ 

    for ( i = 0; i < setting.repeat; i++ ) {                   

	if ( setting.exponential ) {
		udpsock.dataSize = (1<<i);  // Increase the packet size doubly
		if ( udpsock.dataSize > udpsock.packetSize ) // The last one
		    udpsock.dataSize = udpsock.packetSize;
	}

	/**************** Inform server to start UDP test ******************/ 

	sprintf(buff, test_start_str, udpsock.dataSize, 0);
	if ( tcp_send_request(buff, strlen(buff), &tcpsock) == NOTOK ) {
	    perror("Failed to send request.");
	    client_shutdown();
	    exit (1);
	}

	/*************** Start monitoring system information ***************/

	if ( setting.CPUoption ) 
	    start_trace_system(&sysinfo[i+1]);
	start_trace_process(&proinfo[i]);

	/***************** Start UPD throughput test ***********************/

	if ( setting.bidirection ) {
	    if ( client_udp_bi_test (setting.messageSize, setting.testTime, &udpsock) 
		 == NOTOK && error != TIMEOUT && error != DISORDER ) {
		perror("UDP test error.");
		client_shutdown();
		exit (1);
	    }
	} else if ( client_udp_test (setting.messageSize, setting.testTime, &udpsock, 
		    setting.throughput) == NOTOK && error != TIMEOUT && error != DISORDER ) {
	    perror("UDP test error.");
	    client_shutdown();
	    exit (1);
	}

	stop_trace_process(&proinfo[i]);

	if ( setting.CPUoption ) {
	    usleep(1000);
	    stop_trace_system(&sysinfo[i+1]);
	}
	
#ifdef DEBUG 
	fprintf(stderr, " DEBUG: One trip test done, sent Bytes: %lld sent packets: %d\n",
		udpsock.sentBytes, udpsock.sentPackets);
	fprintf(stderr, " DEBUG: Waiting server's test result ...\n");
#endif 
	
	/************* Get server's test result by TCP channel *************/
	
	if ( tcp_get_request(buff, &tcpsock) == NOTOK ) {
	    fprintf(stderr, "Get result error (TCP data channel).\n");
	    client_shutdown();
	    exit(1);
	} else if ( strncmp(buff, test_time_out_str, strlen(test_time_out_str)) == 0 ) {
	    if ( setting.sCPUoption ) {
		if ( tcp_get_request(sysbuff, &tcpsock) == NOTOK ||
		     string_to_sysinfo( &serverinfo[i+1], sysbuff, 2*BUFLEN) == NOTOK ) {
		    perror("Failed to get server's system information.");
		    exit (1);
		}
	    }

	    fprintf(stderr, "UDP key packets lost. Igore the result.\n");
	    if ( setting.writeOption )
		fprintf (output, "#%d UDP key packets lost. Igore the result.\n", i+1);

	    s_rtime_usec[i] = s_utime_usec[i] = s_stime_usec[i] = 0;
	    continue;

	} else if ( sscanf(buff, server_result_str, &server.recvBytes, 
		    &server.recvPackets, &server.sentBytes, &server.sentPackets, 
		    &server.elapsedTime, &s_utime_usec[i], &s_stime_usec[i]) != 7 ) {
		fprintf(stderr, "Failed to parse server's result: %s\n", buff);
		client_shutdown();
		exit(1);
	}
	s_rtime_usec[i] = server.elapsedTime;

	if ( setting.sCPUoption ) {
	    if ( tcp_get_request(sysbuff, &tcpsock) == NOTOK ||
		 string_to_sysinfo( &serverinfo[i+1], sysbuff, 2*BUFLEN) == NOTOK ) {
		perror("Failed to get server's system information.");
		exit (1);
	    }
	}	

	localTP.trial++;
	networkTP.trial++;

	if ( server.elapsedTime <= 0 ) {
	    fprintf(stderr, "Wrong of server's elapsed time! Ignore the result: %s\n", buff);
	    continue;
	}
	
	serverTP = (server.recvBytes+udpsock.recvBytes) * 8.0 / server.elapsedTime; // Network count
	
	if ( networkTP.min > serverTP )
	    networkTP.min = serverTP;
	if ( networkTP.max < serverTP )
	    networkTP.max = serverTP;
	networkTP.sum += serverTP;
	
	clientTP = (server.sentBytes+udpsock.sentBytes) * 8.0 / udpsock.elapsedTime; // local count
	proinfo[i].rtime_sec = udpsock.elapsedTime / 1000000;
	proinfo[i].rtime_usec = udpsock.elapsedTime % 1000000;
	
	/************* Keep the minimum and maximum throughputs ************/	    
	
	if ( localTP.min > clientTP )
	    localTP.min = clientTP;
	if ( localTP.max < clientTP )
	    localTP.max = clientTP;
	localTP.sum += clientTP;

	/****** Compute the packet loss rate of client sending *************/
	
	lossPackets = udpsock.sentPackets - server.recvPackets;
	lossRate = lossPackets * 1.0 / udpsock.sentPackets;
	
	/*********************** Print out test results ********************/ 
	    
	if ( setting.verbose ) {
	    if ( setting.exponential )	
		fprintf(stderr, "Message size: %d\n", udpsock.dataSize);
	    fprintf(stderr, "\n[Client] Sent-bytes: %lld Sent-packets: %d ", 
		    udpsock.sentBytes, udpsock.sentPackets);
	    fprintf(stderr, "Recv-bytes: %lld Recv-Packets: %d\n", 
		    udpsock.recvBytes, udpsock.recvPackets);
	    fprintf(stderr, "[Server] Recv-bytes: %lld Recv-Packets: %d ", 
		    server.recvBytes, server.recvPackets);
	    fprintf(stderr, "Sent-bytes: %lld Sent-Packets: %d\n", 
		    server.sentBytes, server.sentPackets);
	    fprintf(stderr, "Client-time(Sec.): %f  Server-time(Sec.): %f\n", 
		    udpsock.elapsedTime/1000000.0, server.elapsedTime/1000000.0);
	    fprintf(stderr, "Network-throughput(Mbps): %f Local-throughput: %f\n", 
		    serverTP, clientTP);
	    fprintf(stderr, "Lost-packets (c->s): %d  Loss-rate(c->s): %f\n\n", 
		    lossPackets, lossRate);
	} else
	    fprintf(stderr, " (%d) Throughput: %f  Loss-rate: %f\n", 
		    i+1, serverTP, lossRate);
	    
	/*************** Store test results in the file ********************/

    gettimeofday(&tv, NULL);
    ts = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
	if ( setting.writeOption ) {
	    if ( setting.exponential ) {     // exponential throughput test
		if ( !setting.bidirection )
		    fprintf (output, "%-3d%6d%10.3f%10.3f%10d%12lld%10d%12lld%10d%10.3f%17.2f\n", 
			 i+1, udpsock.dataSize, serverTP, clientTP, udpsock.sentPackets, 
			 udpsock.sentBytes, server.recvPackets, server.recvBytes, 
			 lossPackets, lossRate, ts);
		else
		    fprintf (output, "%-3d%6d%10.3f%10.3f%10d%12lld%10d%12lld%10d%12lld%10d%12lld%12.3f%17.2f\n", 
			 i+1, udpsock.dataSize, serverTP, clientTP, udpsock.sentPackets, 
			 udpsock.sentBytes, server.recvPackets, server.recvBytes, udpsock.recvPackets, 
			     udpsock.recvBytes, server.sentPackets, server.sentBytes, lossRate, ts);
	    }
	    else if ( !setting.bidirection )   // unidirectional throughput test 
		fprintf (output, "%-3d%13.4f%12.4f%11d%12lld%11d%12lld%10d%10.3f%17.2f\n", 
			 i+1, serverTP, clientTP, udpsock.sentPackets, udpsock.sentBytes, 
			 server.recvPackets, server.recvBytes, lossPackets, lossRate, ts);
	    else {                             // bidirectional throughput test 
		fprintf(output, "%-3d%10.3f%11.3f%9d", i+1, serverTP, clientTP, udpsock.sentPackets);
		fprintf(output, "%12lld%9d%12lld", udpsock.sentBytes, server.recvPackets, server.recvBytes);
		fprintf(output, "%9d%12lld%9d", udpsock.recvPackets, udpsock.recvBytes, server.sentPackets);
		fprintf(output, "%12lld%9.3f%17.2f\n", server.sentBytes, lossRate, ts);
	    } // bidriection test
	} // if write option

    } // for loop of repeat


    /********************** Inform server the end of the session ***********/

    sprintf(buff, test_end_str);
    if ( tcp_send_request (buff, strlen(buff), &tcpsock) == NOTOK )
	fprintf(stderr, "Close session error.");

    if ( setting.CPUoption ) { // record the post-test system info
	if ( start_trace_system( &sysinfo[setting.repeat+1] ) == NOTOK ) {
	    perror("Failed to trace system in final state.");
	    exit (1);
	}
	sleep(1);
	if ( stop_trace_system( &sysinfo[setting.repeat+1] ) == NOTOK ) {
	    perror("Failed to trace system in final state.");
	    exit (1);
	}
	if ( setting.sCPUoption ) {
	    if ( tcp_get_request(sysbuff, &tcpsock) == NOTOK ||
		 string_to_sysinfo( &serverinfo[setting.repeat+1],
				    sysbuff, 2*BUFLEN) == NOTOK ) {
		perror("Failed to get server's last syslog.");
		exit (1);
	    }
	}
    }

    /***** Compute the average throughput for fixed-size message tests *****/

    if ( !setting.exponential && setting.writeOption && localTP.trial > 2 ) {
	
	localTP.avg = localTP.sum/localTP.trial; 
	networkTP.avg = networkTP.sum/localTP.trial; 

	fprintf(output, "\n# Local Average: %10f  Minimum: %10f  Maximum: %10f\n", 
		localTP.avg, localTP.min, localTP.max);
	fprintf(output, "# Network Average: %10f  Minimum: %10f  Maximum: %10f\n", 
		networkTP.avg, networkTP.min, networkTP.max);
    } 

    if ( setting.writeOption ) {
	fprintf(output, "\n# Process information for each test: \n\n");
	fprintf(output, "#         Client     C-process   C-process      Server     S-process   S-process\n");
	fprintf(output, "#      Elapsed-time  User-mode  System-mode  Elapsed-time  User-mode  System-mode\n");
	fprintf(output, "#       (Seconds)    (Seconds)   (Seconds)    (Seconds)    (Seconds)   (Seconds)\n");
	for ( i = 0; i < setting.repeat; i++ ) {
	    fprintf(output, "#%-4d%11.2f%13.2f%12.2f%13.2f%13.2f%12.2f\n", i+1, 
		    (double)proinfo[i].rtime_sec + proinfo[i].rtime_usec/1000000.0,
		    (double)proinfo[i].utime_sec + proinfo[i].utime_usec/1000000.0,
		    (double)proinfo[i].stime_sec + proinfo[i].stime_usec/1000000.0,
		    s_rtime_usec[i]/1000000.0, s_utime_usec[i]/1000000.0, s_stime_usec[i]/1000000.0);
	}
	fprintf(output, "\n");
	fclose(output); 

	fprintf(stderr, "Test done! The results are stored in file \"%s\"\n", filename);
	if ( setting.CPUoption ) {
	    strcpy(buff, filename);
	    strcat(buff, ".c_log");
	    if ( write_sys_info(sysinfo, setting.repeat+2, buff, curtime, localhost) == OK )
		fprintf(stderr, "Local-syslog: \"%s\"  ", buff); 
	    strcpy(buff, filename);
	    strcat(buff, ".s_log");
	    if ( setting.sCPUoption && 
		 write_sys_info(serverinfo, setting.repeat+2, buff, curtime, hostname) == OK )
		fprintf(stderr, "server-syslog: \"%s\"", buff); 
	    fprintf(stderr, "\n");
	}	
	if ( setting.plotOption && write_plot() == OK ) { 
	    fprintf(stderr, "Plot-file: \"%s\". ", plotname);
	    fprintf(stderr, "Use \"gnuplot %s\" to plot the data\n", plotname);
	}
	fclose(output);
    } else 
	fprintf(stderr, "Test done!\n");

    /*************************** Close the connection **********************/

    client_shutdown();   
    return 0;

}  // end of main function 
Пример #15
0
void client_shutdown_char(char *c)
{
	client_shutdown();
}
Пример #16
0
int main(int argc, char *argv[])
{
	int listenfd;
	int res = 0;
	int lfd;
	struct flock lock;
	char pids[10];

	parse_opts(argc, argv);

	argc -= optind;
	argv += optind;

	if (!foreground) {
		verbose += LL_WARNING;
		log_enable_syslog();
	} else {
		verbose += LL_NOTICE;
	}

	/* set log level to specified verbosity */
	log_level = verbose;

	usbmuxd_log(LL_NOTICE, "usbmuxd v%s starting up", PACKAGE_VERSION);
	should_exit = 0;
	should_discover = 0;

	set_signal_handlers();
	signal(SIGPIPE, SIG_IGN);

	res = lfd = open(lockfile, O_WRONLY|O_CREAT, 0644);
	if(res == -1) {
		usbmuxd_log(LL_FATAL, "Could not open lockfile");
		goto terminate;
	}
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_pid = 0;
	fcntl(lfd, F_GETLK, &lock);
	close(lfd);
	if (lock.l_type != F_UNLCK) {
		if (opt_exit) {
			if (lock.l_pid && !kill(lock.l_pid, 0)) {
				usbmuxd_log(LL_NOTICE, "Sending signal %d to instance with pid %d", exit_signal, lock.l_pid);
				res = 0;
				if (kill(lock.l_pid, exit_signal) < 0) {
					usbmuxd_log(LL_FATAL, "Could not deliver signal %d to pid %d", exit_signal, lock.l_pid);
					res = -1;
				}
				goto terminate;
			} else {
				usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
				res = -1;
				goto terminate;
			}
		} else {
			if (!opt_disable_hotplug) {
				usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid);
				res = -1;
			} else {
				usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). Telling it to check for devices.", lock.l_pid);
				if (lock.l_pid && !kill(lock.l_pid, 0)) {
					usbmuxd_log(LL_NOTICE, "Sending signal SIGUSR2 to instance with pid %d", lock.l_pid);
					res = 0;
					if (kill(lock.l_pid, SIGUSR2) < 0) {
						usbmuxd_log(LL_FATAL, "Could not deliver SIGUSR2 to pid %d", lock.l_pid);
						res = -1;
					}
				} else {
					usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
					res = -1;
				}
			}
			goto terminate;
		}
	}
	unlink(lockfile);

	if (opt_exit) {
		usbmuxd_log(LL_NOTICE, "No running instance found, none killed. Exiting.");
		goto terminate;
	}

	if (!foreground) {
		if ((res = daemonize()) < 0) {
			fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
			usbmuxd_log(LL_FATAL, "Could not daemonize!");
			goto terminate;
		}
	}

	// now open the lockfile and place the lock
	res = lfd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
	if(res < 0) {
		usbmuxd_log(LL_FATAL, "Could not open lockfile");
		goto terminate;
	}
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	if ((res = fcntl(lfd, F_SETLK, &lock)) < 0) {
		usbmuxd_log(LL_FATAL, "Lockfile locking failed!");
		goto terminate;
	}
	sprintf(pids, "%d", getpid());
	if ((size_t)(res = write(lfd, pids, strlen(pids))) != strlen(pids)) {
		usbmuxd_log(LL_FATAL, "Could not write pidfile!");
		if(res >= 0)
			res = -2;
		goto terminate;
	}

	// set number of file descriptors to higher value
	struct rlimit rlim;
	getrlimit(RLIMIT_NOFILE, &rlim);
	rlim.rlim_max = 65536;
	setrlimit(RLIMIT_NOFILE, (const struct rlimit*)&rlim);

	usbmuxd_log(LL_INFO, "Creating socket");
	res = listenfd = create_socket();
	if(listenfd < 0)
		goto terminate;

#ifdef HAVE_LIBIMOBILEDEVICE
	const char* userprefdir = config_get_config_dir();
	struct stat fst;
	memset(&fst, '\0', sizeof(struct stat));
	if (stat(userprefdir, &fst) < 0) {
		if (mkdir(userprefdir, 0775) < 0) {
			usbmuxd_log(LL_FATAL, "Failed to create required directory '%s': %s", userprefdir, strerror(errno));
			res = -1;
			goto terminate;
		}
		if (stat(userprefdir, &fst) < 0) {
			usbmuxd_log(LL_FATAL, "stat() failed after creating directory '%s': %s", userprefdir, strerror(errno));
			res = -1;
			goto terminate;
		}
	}

	// make sure permission bits are set correctly
	if (fst.st_mode != 02775) {
		if (chmod(userprefdir, 02775) < 0) {
			usbmuxd_log(LL_WARNING, "chmod(%s, 02775) failed: %s", userprefdir, strerror(errno));
		}
	}
#endif

	// drop elevated privileges
	if (drop_privileges && (getuid() == 0 || geteuid() == 0)) {
		struct passwd *pw;
		if (!drop_user) {
			usbmuxd_log(LL_FATAL, "No user to drop privileges to?");
			res = -1;
			goto terminate;
		}
		pw = getpwnam(drop_user);
		if (!pw) {
			usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user);
			res = -1;
			goto terminate;
		}
		if (pw->pw_uid == 0) {
			usbmuxd_log(LL_INFO, "Not dropping privileges to root");
		} else {
#ifdef HAVE_LIBIMOBILEDEVICE
			/* make sure the non-privileged user has proper access to the config directory */
			if ((fst.st_uid != pw->pw_uid) || (fst.st_gid != pw->pw_gid)) {
				if (chown(userprefdir, pw->pw_uid, pw->pw_gid) < 0) {
					usbmuxd_log(LL_WARNING, "chown(%s, %d, %d) failed: %s", userprefdir, pw->pw_uid, pw->pw_gid, strerror(errno));
				}
			}
#endif

			if ((res = initgroups(drop_user, pw->pw_gid)) < 0) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set supplementary groups)");
				goto terminate;
			}
			if ((res = setgid(pw->pw_gid)) < 0) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set group ID to %d)", pw->pw_gid);
				goto terminate;
			}
			if ((res = setuid(pw->pw_uid)) < 0) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set user ID to %d)", pw->pw_uid);
				goto terminate;
			}

			// security check
			if (setuid(0) != -1) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
				res = -1;
				goto terminate;
			}
			if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
				res = -1;
				goto terminate;
			}
			usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user);
		}
	}

	client_init();
	device_init();
	usbmuxd_log(LL_INFO, "Initializing USB");
	if((res = usb_init()) < 0)
		goto terminate;

	usbmuxd_log(LL_INFO, "%d device%s detected", res, (res==1)?"":"s");

	usbmuxd_log(LL_NOTICE, "Initialization complete");

	if (report_to_parent)
		if((res = notify_parent(0)) < 0)
			goto terminate;

	if(opt_disable_hotplug) {
		usbmuxd_log(LL_NOTICE, "Automatic device discovery on hotplug disabled.");
		usb_autodiscover(0); // discovery to be triggered by new instance
	}
	if (opt_enable_exit) {
		usbmuxd_log(LL_NOTICE, "Enabled exit on SIGUSR1 if no devices are attached. Start a new instance with \"--exit\" to trigger.");
	}

	res = main_loop(listenfd);
	if(res < 0)
		usbmuxd_log(LL_FATAL, "main_loop failed");

	usbmuxd_log(LL_NOTICE, "usbmuxd shutting down");
	device_kill_connections();
	usb_shutdown();
	device_shutdown();
	client_shutdown();
	usbmuxd_log(LL_NOTICE, "Shutdown complete");

terminate:
	log_disable_syslog();

	if (res < 0)
		res = -res;
	else
		res = 0;
	if (report_to_parent)
		notify_parent(res);

	return res;
}
Пример #17
0
int main(int argc, char *argv[]) {
    char *host       = NULL;
    char *renderer   = NULL;
    int   width      = 800;
    int   height     = 600;
    int   fullscreen = 0;

#ifdef EVENT_HOST
    host = EVENT_HOST;
#endif

#ifdef DEFAULT_RENDERER
    renderer = TOSTRING(DEFAULT_RENDERER);
#endif

    // GUI Environment setzt default Renderer um.
    if (getenv("GUI"))
        renderer = getenv("GUI");

#ifdef WIN32
    char *sep = strrchr(argv[0], '\\');
    if (sep) { *sep = '\0'; chdir(argv[0]); }

    // Spezialfaelle fuer Windows Screensaver Aufrufe
    if (argc == 2 && stricmp(argv[1], "/s") == 0) {
        host  = "infon.dividuum.de";
        width = 1024, height = 768, fullscreen = 1;
        goto screen_saver_start;
    } else if (argc == 3 && stricmp(argv[1], "/p") == 0) {
        exit(EXIT_SUCCESS);
    } else if (argc == 2 && strstr(argv[1], "/c:") == argv[1]) {
        die("There are no settings");
    }
#endif

    // Keine Fehler auf stderr
    opterr = 0;

    int opt; 
    while ((opt = getopt(argc, argv, ":fvx:y:r:h")) != -1) {
        switch (opt) {
            case '?': die("you specified an unknown option -%c.", optopt);
            case ':': die("missing argument to option -%c.", optopt);
            case 'r': renderer   = optarg;          break;
            case 'f': fullscreen = 1;               break;
            case 'x': width      = atoi(optarg);    break;
            case 'y': height     = atoi(optarg);    break;
            case 'h': die("usage: %s [-r <renderer>] [-f] [-x <width>] [-y <height>] [-v] [-h] <server[:port]>\n"
                          "\n"
                          " -r <renderer>    - renderer to use (sdl_gui, gl_gui, ...)\n"
                          " -x <width>       - initial screen width.\n"
                          " -y <height>      - initial screen height.\n"
                          " -f               - start in fullscreen mode.\n"
                          " -v               - display version information.\n"
                          " -h               - this help.\n"
                          "\n"
                          "<server[:port]>   - ip/hostname of an infon game server.\n"
                          "                    if no port is given, 1234 is used.\n", argv[0]);
            case 'v': info(); exit(EXIT_SUCCESS);
        }
    }

    switch (argc - optind) {
        case 0:  break;
        case 1:  host = argv[optind]; break;
        default: die("you specified more than one game server hostname");
    }

    if (!renderer)
        die("no renderer specified. use the '-r <renderer>' option");

#ifdef WIN32
    if (!host) {
        if (yesno("You did not specify a game server.\nConnect to 'infon.dividuum.de:1234'?"))
            host = "infon.dividuum.de";
        else
            die("You must supply the game servers hostname\n"
                "as a command line parameter.\n\n"
                "Example: 'infon.exe infon.dividuum.de'\n\n"
                "Visit http://infon.dividuum.de/ for help.");
    } 
#else
    if (!host)
        die("usage: %s [options] <server[:port]>\n"
            "see %s -h for a full list of options", argv[0], argv[0]);
#endif


#ifndef WIN32
    signal(SIGTERM, sighandler);
    signal(SIGINT,  sighandler);
    signal(SIGPIPE, SIG_IGN);
#else
screen_saver_start:
#endif

    srand(time(NULL));
    gettimeofday(&start, NULL);

    if (!renderer_init(renderer)) 
        die("cannot initialize the renderer '%s'", renderer);

    if (!renderer_open(width, height, fullscreen))
        die("cannot start the renderer '%s'. sorry", renderer);

    client_init(host);
    client_game_init();

    int lastticks = get_tick();
    while (!signal_received && !renderer_wants_shutdown() && client_is_connected()) {
        int nowticks = get_tick();
        int delta = nowticks - lastticks;

        if (nowticks < lastticks || nowticks > lastticks + 1000) {
            // Timewarp?
            lastticks = nowticks;
            continue;
        }
        lastticks = nowticks;

        // IO Lesen/Schreiben
        client_tick(delta);
        client_creature_move(delta);
        renderer_tick(game_time, delta);

        game_time += delta;
    }

    client_game_shutdown();
    client_shutdown();

    renderer_close();
    renderer_shutdown();
    return EXIT_SUCCESS; 
}