void collabclient_sessionDisconnect( FontViewBase* fv ) { #ifdef BUILD_COLLAB cloneclient_t *cc = fv->collabClient; fv->collabState = cs_disconnected; fv->collabClient = 0; FVTitleUpdate( fv ); collabclient_free( (void**)&cc ); #endif }
/** * A timeout function which is called after a given idle period to * alert the user if we have not received a reply from the server yet. * * If we don't get a reply in time then the user experience will * suffer greatly (UI elements jumping around etc) so we ask the user * if they want to start again or disconnect. */ static void collabclient_roundTripTimer( void* ccvp ) { cloneclient_t *cc = (cloneclient_t*)ccvp; // printf("collabclient_roundTripTimer() cc: %p\n", cc ); // printf("collabclient_roundTripTimer() waitingseq: %d\n", cc->roundTripTimerWaitingSeq ); if( cc->roundTripTimerWaitingSeq ) { cc->roundTripTimerWaitingSeq = 0; char *buts[3]; buts[0] = _("_Reconnect"); buts[1] = _("_Disconnect"); buts[2] = NULL; if ( gwwv_ask(_("Network Issue"), (const char **) buts,0,1, _("FontForge expected some input from the server by now.\nWould you like to try to reconnect to the collaboration session?"))==1 ) { // break session FontView* fv = FontViewFind( FontViewFind_byCollabPtr, cc ); if( fv ) { printf("fv:%p\n", fv ); fv->b.collabState = cs_disconnected; fv->b.collabClient = 0; FVTitleUpdate( &fv->b ); } collabclient_free( (void**)&cc ); return; } collabclient_sessionReconnect( cc ); } }
FontViewBase* collabclient_sessionJoin( void* ccvp, FontView *fv ) { FontViewBase* ret = 0; #ifdef BUILD_COLLAB cloneclient_t* cc = (cloneclient_t*)ccvp; printf("collabclient_sessionJoin(top)\n"); // Get state snapshot cc->sequence = 0; zstr_sendm (cc->snapshot, "ICANHAZ?"); zstr_send (cc->snapshot, SUBTREE); // if we wait for timeoutMS millisec then we assume failure // timeWaitedMS is used to keep track of how long we have waited kvmsg_t* lastSFD = 0; int timeWaitedMS = 0; int timeoutMS = pref_collab_sessionJoinTimeoutMS; while (true) { printf("timeoutMS:%d timeWaitedMS:%d\n", timeoutMS, timeWaitedMS ); if( timeWaitedMS >= timeoutMS ) { char* addrport = collabclient_makeAddressString( cc->address, cc->port ); gwwv_post_error(_("FontForge Collaboration"), _("Failed to connect to server session at %s"), addrport ); return 0; } kvmsg_t *kvmsg = kvmsg_recv_full( cc->snapshot, ZMQ_DONTWAIT ); if (!kvmsg) { int msToWait = 50; g_usleep( msToWait * 1000 ); timeWaitedMS += msToWait; continue; } /* kvmsg_t *kvmsg = kvmsg_recv (cc->snapshot); */ /* if (!kvmsg) */ /* break; // Interrupted */ if (streq (kvmsg_key (kvmsg), "KTHXBAI")) { cc->sequence = kvmsg_sequence (kvmsg); printf ("I: received snapshot=%d\n", (int) cc->sequence); kvmsg_destroy (&kvmsg); // Done break; } printf ("I: storing seq=%ld ", kvmsg_sequence (kvmsg)); if( kvmsg_get_prop (kvmsg, "type") ) printf(" type:%s", kvmsg_get_prop (kvmsg, "type") ); printf ("\n"); if( !strcmp(kvmsg_get_prop (kvmsg, "type"), MSG_TYPE_SFD )) { if( !lastSFD || kvmsg_sequence (kvmsg) > kvmsg_sequence (lastSFD)) { lastSFD = kvmsg; } size_t data_size = kvmsg_size(lastSFD); printf("data_size:%ld\n", data_size ); } kvmsg_store (&kvmsg, cc->kvmap); } printf("collabclient_sessionJoin(done with netio getting snapshot)\n"); printf("collabclient_sessionJoin() lastSFD:%p\n", lastSFD ); // int rc = 0; // void* out = 0; // rc = zhash_foreach ( cc->kvmap, collabclient_sessionJoin_findSFD_foreach_fn, &out ); // printf("collabclient_sessionJoin() last sfd:%p\n", out ); if( !lastSFD ) { gwwv_post_error(_("FontForge Collaboration"), _("No Font Snapshot received from the server")); return 0; } if( lastSFD ) { int openflags = 0; char filename[PATH_MAX]; snprintf(filename, PATH_MAX, "%s/fontforge-collab-import-%d.sfd",getTempDir(),getpid()); GFileWriteAll( filename, kvmsg_body (lastSFD) ); /* * Since we are creating a new fontview window for the collab session * we "hand over" the collabClient from the current fontview used to join * the session to the fontview which owns the sfd from the wire. */ FontViewBase* newfv = ViewPostScriptFont( filename, openflags ); newfv->collabClient = cc; fv->b.collabClient = 0; newfv->collabState = cs_client; FVTitleUpdate( newfv ); collabclient_notifySessionJoining( cc, newfv ); ret = newfv; /* cloneclient_t* newc = collabclient_new( cc->address, cc->port ); */ /* collabclient_sessionJoin( newc, fv ); */ } printf("applying updates from server that were performed after the SFD snapshot was done...\n"); kvmap_visit( cc->kvmap, kvmsg_sequence (lastSFD), collabclient_sessionJoin_processmsg_foreach_fn, cc ); /* struct collabclient_sessionJoin_processUpdates_foreach_args args; */ /* args.cc = cc; */ /* args.lastSFD = lastSFD; */ /* rc = zhash_foreach ( cc->kvmap, collabclient_sessionJoin_processUpdates_foreach_fn, &args ); */ printf("collabclient_sessionJoin(complete)\n"); #endif return ret; }
void collabclient_sessionStart( void* ccvp, FontView *fv ) { #ifdef BUILD_COLLAB cloneclient_t* cc = (cloneclient_t*)ccvp; // // Fire up the fontforge-internal-collab-server process... // { char command_line[PATH_MAX+1]; #if defined(__MINGW32__) sprintf(command_line, "'%s/ffcollab.bat' %d", getGResourceProgramDir(), cc->port ); #else sprintf(command_line, "%s/bin/FontForgeInternal/fontforge-internal-collab-server %d", getLibexecDir_NonWindows(), cc->port ); #endif printf("command_line:%s\n", command_line ); GError * error = 0; if(!getenv("FONTFORGE_USE_EXISTING_SERVER")) { int rc = g_spawn_command_line_async( command_line, &error ); if( !rc ) { fprintf(stderr, "Error starting collab server\n"); if( error ) fprintf(stderr, "code:%d message:%s\n", error->code, error->message ); } } } printf("Starting a session, sending it the current SFD as a baseline...\n"); if( !ff_uuid_isValid( fv->b.sf->collab_uuid)) ff_uuid_generate( fv->b.sf->collab_uuid ); strcpy( cc->unacknowledged_beacon_uuid, fv->b.sf->collab_uuid ); time( &cc->unacknowledged_beacon_sendTime ); int s2d = 0; char filename[PATH_MAX]; snprintf(filename, PATH_MAX, "%s/fontforge-collab-start-%d.sfd", getTempDir(), getpid()); int ok = SFDWrite(filename,fv->b.sf,fv->b.map,fv->b.normal,s2d); printf("connecting to server...3 ok:%d\n",ok); if ( ok ) { char* sfd = GFileReadAll( filename ); printf("connecting to server...4 sfd:%p\n", sfd ); collabclient_sendSFD( cc, sfd, fv->b.sf->collab_uuid, fv->b.sf->fontname ); } GFileUnlink(filename); printf("connecting to server...sent the sfd for session start.\n"); fv->b.collabState = cs_server; FVTitleUpdate( &fv->b ); collabclient_setHaveLocalServer( 1 ); beacon_moon_bounce_timerID = BackgroundTimer_new( 3000, beacon_moon_bounce_timer_callback, cc ); collabclient_notifySessionJoining( cc, (FontViewBase*)fv ); #endif }