static void test_tcp_pair_cli (void *args, zctx_t *ctx, void *pipe) { vtx_t *vtx = vtx_new (ctx); int rc = vtx_tcp_load (vtx, FALSE); assert (rc == 0); char *port = zstr_recv (pipe); void *pair = vtx_socket (vtx, ZMQ_PAIR); assert (pair); rc = vtx_connect (vtx, pair, "tcp://localhost:%s", port); assert (rc == 0); int sent = 0; int recd = 0; while (!zctx_interrupted) { zstr_send (pair, "ICANHAZ?"); sent++; char *reply = zstr_recv_nowait (pair); if (reply) { recd++; free (reply); } char *end = zstr_recv_nowait (pipe); if (end) { free (end); zstr_send (pipe, "OK"); break; } } zclock_log ("I: PAIR CLI: sent=%d recd=%d", sent, recd); free (port); vtx_destroy (&vtx); }
static void test_tcp_pub (void *args, zctx_t *ctx, void *pipe) { vtx_t *vtx = vtx_new (ctx); int rc = vtx_tcp_load (vtx, FALSE); assert (rc == 0); char *port = zstr_recv (pipe); // Create publisher socket and bind to all network interfaces void *publisher = vtx_socket (vtx, ZMQ_PUB); assert (publisher); rc = vtx_bind (vtx, publisher, "tcp://*:%s", port); assert (rc == 0); int sent = 0; while (!zctx_interrupted) { zstr_sendf (publisher, "NOM %04x", randof (0x10000)); sent++; char *end = zstr_recv_nowait (pipe); if (end) { free (end); zstr_send (pipe, "OK"); break; } } zclock_log ("I: PUB: sent=%d", sent); free (port); vtx_destroy (&vtx); }
int game_thread( void * _parms ) { GameThreadParms * parms = (GameThreadParms*)_parms; GameState gs; SharedRenderState rs; game_init( gs, rs ); gs.zmq_control_socket = zsocket_new( parms->zmq_context, ZMQ_PAIR ); { int ret = zsocket_connect( gs.zmq_control_socket, "inproc://control_game" ); assert( ret == 0 ); } gs.zmq_render_socket = zsocket_new( parms->zmq_context, ZMQ_PAIR ); zsocket_bind( gs.zmq_render_socket, "inproc://game_render" ); gs.zmq_input_req = zsocket_new( parms->zmq_context, ZMQ_REQ ); { int ret = zsocket_connect( gs.zmq_input_req, "inproc://input" ); assert( ret == 0 ); } unsigned int baseline = SDL_GetTicks(); int framenum = 0; while ( true ) { unsigned int now = SDL_GetTicks(); unsigned int target_frame = ( now - baseline ) / GAME_DELAY; if ( framenum <= target_frame ) { framenum++; // NOTE: build the state of the world at t = framenum * GAME_DELAY, // under normal conditions that's a time in the future // (the exception to that is if we are catching up on ticking game frames) game_tick( now, gs, rs ); // notify the render thread that a new game state is ready. // on the next render frame, it will start interpolating between the previous state and this new one zstr_sendf( gs.zmq_render_socket, "%d %f %f %f %f %f %f %f %f %f", baseline + framenum * GAME_DELAY, rs.position.x, rs.position.y, rs.orientation.w, rs.orientation.x, rs.orientation.y, rs.orientation.z, rs.smoothed_angular.x, rs.smoothed_angular.y, rs.smoothed_angular.z ); } else { int ahead = framenum * GAME_DELAY - ( now - baseline ); assert( ahead > 0 ); printf( "game sleep %d ms\n", ahead ); SDL_Delay( ahead ); } char * cmd = zstr_recv_nowait( gs.zmq_control_socket ); if ( cmd != NULL ) { assert( strcmp( cmd, "stop" ) == 0 ); free( cmd ); break; } } return 0; }
static void zeromq_beacon_fd_callback(int zeromq_fd, void* datas ) { // cloneclient_t* cc = (cloneclient_t*)datas; // printf("zeromq_beacon_fd_callback(top)\n"); int opt = 0; size_t optsz = sizeof(int); zmq_getsockopt( zbeacon_socket (client_beacon), ZMQ_EVENTS, &opt, &optsz ); // printf("zeromq_beacon_fd_callback(2) opt:%d\n", opt ); if( opt & ZMQ_POLLIN ) { // printf("zeromq_beacon_fd_callback() have message!\n"); while( 1 ) { char *ipaddress = zstr_recv_nowait (zbeacon_socket (client_beacon)); // printf("zeromq_beacon_fd_callback() have data? p:%p\n", ipaddress ); if( ipaddress ) { // printf("zeromq_beacon_fd_callback() have message! ip:%s\n", ipaddress ); zframe_t *content = zframe_recv_nowait (zbeacon_socket (client_beacon)); if( content ) { beacon_announce_t* ba = (beacon_announce_t*)zframe_data(content); // printf("uuid:%s\n", ba->uuid ); // printf("user:%s\n", ba->username ); // printf("mach:%s\n", ba->machinename ); // if( ba->version >= 2 && ff_uuid_isValid(ba->uuid) ) { // printf("have a beacon back for xuid:%s\n", ba->uuid ); // } beacon_announce_t* copy = g_malloc( sizeof(beacon_announce_t)); memcpy( copy, ba, sizeof(beacon_announce_t)); copy->last_msg_from_peer_time = time(0); copy->port = ntohs( copy->port ); strncpy( copy->ip, ipaddress, beacon_announce_ip_sz ); g_hash_table_replace( peers, copy->uuid, copy ); zframe_destroy (&content); } free (ipaddress); } else break; } } zeromq_beacon_show_peers(0); }
/** * Reply to a ping request from FontForge on localhost */ static int s_ping (zloop_t *loop, zmq_pollitem_t *poller, void *args) { clonesrv_t *self = (clonesrv_t *) args; char* p = zstr_recv_nowait( self->ping ); if( p && !strcmp(p,"quit")) { if( service_beacon ) zbeacon_destroy( &service_beacon ); exit(0); } zstr_send( self->ping, "pong" ); return 0; }
static void collabclient_sniffForLocalServer_timer( void* udata ) { collabclient_sniffForLocalServer_t* cc = (collabclient_sniffForLocalServer_t*)udata; // printf("collabclient_sniffForLocalServer_timer()\n"); char* p = zstr_recv_nowait( cc->socket ); if( p ) { // printf("collabclient_sniffForLocalServer_timer() p:%s\n", p); if( !strcmp(p,"pong")) { // printf("******* have local server!\n"); cc->haveServer = 1; } } }
int render_thread( void * _parms ) { RenderThreadParms * parms = (RenderThreadParms*)_parms; RenderThreadSockets rsockets; void * zmq_control_socket = zsocket_new( parms->zmq_context, ZMQ_PAIR ); { int ret = zsocket_connect( zmq_control_socket, "inproc://control_render" ); assert( ret == 0 ); } void * zmq_game_socket = zsocket_new( parms->zmq_context, ZMQ_PAIR ); { int ret = zsocket_connect( zmq_game_socket, "inproc://game_render" ); // NOTE: since both render thread and game thread get spun at the same time, // and the connect needs to happen after the bind, // it's possible this would fail on occasion? just loop a few times and retry? assert( ret == 0 ); } rsockets.zmq_input_req = zsocket_new( parms->zmq_context, ZMQ_REQ ); { int ret = zsocket_connect( rsockets.zmq_input_req, "inproc://input" ); assert( ret == 0 ); } #ifdef __APPLE__ OSX_GL_set_current( parms->ogre_window ); #else // NOTE: no SDL_GL_ on OSX when Ogre is in charge of the context! SDL_GL_MakeCurrent( parms->window, parms->gl_context ); #endif // internal render state, not part of the interpolation RenderState rs; // always interpolating between two states SharedRenderState srs[2]; unsigned int srs_index = 0; srs[0].game_time = srs[1].game_time = 0; render_init( parms, rs, srs[0] ); while ( true ) { char * cmd = zstr_recv_nowait( zmq_control_socket ); if ( cmd != NULL ) { assert( strcmp( cmd, "stop" ) == 0 ); free( cmd ); break; // exit the thread } while ( true ) { // any message from the game thread? char * game_tick = zstr_recv_nowait( zmq_game_socket ); if ( game_tick == NULL ) { break; } srs_index ^= 1; parse_render_state( rs, srs[ srs_index ], game_tick ); free( game_tick ); } // skip rendering until enough data has come in to support interpolation if ( srs[0].game_time == srs[1].game_time ) { // 0 == 0 continue; } unsigned int pre_render_time = SDL_GetTicks(); float ratio = (float)( pre_render_time - srs[ srs_index ^ 1 ].game_time ) / (float)( srs[ srs_index ].game_time - srs[ srs_index ^ 1 ].game_time ); printf( "render ratio %f\n", ratio ); interpolate_and_render( rsockets, rs, ratio, srs[ srs_index ^ 1 ], srs[ srs_index ] ); parms->root->_fireFrameStarted(); parms->root->renderOneFrame(); parms->root->_fireFrameRenderingQueued(); if ( parms->gl_context != NULL ) { // glcontext != NULL <=> SDL initialized the GL context and manages the buffer swaps SDL_GL_SwapWindow( parms->window ); } parms->root->_fireFrameEnded(); // 'render latency': how late is the image we displayed // if vsync is off, it's the time it took to render the frame // if vsync is on, it's render time + time waiting for the buffer swap // NOTE: could display it terms of ratio also? unsigned int post_render_time = SDL_GetTicks(); printf( "render latency %d ms\n", post_render_time - pre_render_time ); } return 0; }