Exemple #1
0
void CNet::FlushNet(void)
{
    for (int a=0; a<gs->activePlayers; a++) {
        Connection* c=&connections[a];
        if(c->active && c->outgoingLength>0) {
            FlushConnection(a);
        }
    }
}
Exemple #2
0
void CNet::Update(void)
{
    Uint64 t;
    t = SDL_GetTicks();
    curTime=float(t)/1000.f;
    if(playbackDemo)
        ReadDemoFile();
    if(onlyLocal) {
        return;
    }
    sockaddr_in from;
    socklen_t fromsize;
    fromsize=sizeof(from);
    int r;
    unsigned char inbuf[16000];
    if(connected)
        while(true) {
            if((r=recvfrom(mySocket,(char*)inbuf,16000,0,(sockaddr*)&from,&fromsize))==SOCKET_ERROR) {
                if (IsFakeError())
                    break;
                char test[500];
                sprintf(test,"Error receiving data. %i %d",(int)imServer,WSAGetLastError());
                handleerror(NULL,test,"SHUTDOWN ERROR",MBF_OK | MBF_INFO);
                exit(0);
            }
            int conn=ResolveConnection(&from);
            if(conn==-1) {
                if(waitOnCon && r>=12 && (*(int*)inbuf)==0 && (*(int*)&inbuf[4])==-1 && inbuf[8]==0 && inbuf[9]==NETMSG_ATTEMPTCONNECT && inbuf[11]==NETWORK_VERSION) {
                    conn=InitNewConn(&from,false,inbuf[10]);
                } else {
                    continue;
                }
            }
            inInitialConnect=false;
            int packetNum=(*(int*)inbuf);
            ProcessRawPacket(inbuf,r,conn);
        }

    for(int a=0; a<gs->activePlayers; ++a) {
        Connection* c=&connections[a];
        if(c->localConnection || !c->active)
            continue;
        std::map<int,Packet*>::iterator wpi;
        while((wpi=c->waitingPackets.find(c->lastInOrder+1))!=c->waitingPackets.end()) {		//process all in order packets that we have waiting
            if(c->readyLength+wpi->second->length>=NETWORK_BUFFER_SIZE) {
                logOutput.Print("Overflow in incoming network buffer");
                break;
            }
            memcpy(&c->readyData[c->readyLength],wpi->second->data,wpi->second->length);
            c->readyLength+=wpi->second->length;
            delete wpi->second;
            c->waitingPackets.erase(wpi);
            c->lastInOrder++;
        }
        if(inInitialConnect && c->lastSendTime<curTime-1) {		//server hasnt responded so try to send the connection attempt again
            SendRawPacket(a,c->unackedPackets[0]->data,c->unackedPackets[0]->length,0);
            c->lastSendTime=curTime;
        }

        if(c->lastSendTime<curTime-5 && !inInitialConnect) {		//we havent sent anything for a while so send something to prevent timeout
            SendData(NETMSG_HELLO);
        }
        if(c->lastSendTime<curTime-0.2f && !c->waitingPackets.empty()) {	//we have at least one missing incomming packet lying around so send a packet to ensure the other side get a nak
            SendData(NETMSG_HELLO);
        }
        if(c->lastReceiveTime < curTime-(inInitialConnect ? 40 : 30)) {		//other side has timed out
            c->active=false;
        }

        if(c->outgoingLength>0 && (c->lastSendTime < (curTime-0.2f+c->outgoingLength*0.01f) || c->lastSendFrame < gs->frameNum-1)) {
            FlushConnection(a);
        }
    }
}
/**
 * This is the main routine responsible for replicating our GL state
 * for a new VNC viewer.  Called when we detect that a new VNC viewer
 * has been started.
 * \param ipaddress  the IP address where the new viewer is running.
 */
void
replicatespuReplicate(int ipaddress) 
{
	GET_THREAD(thread);
	struct in_addr addr;
	char *hosturl;
	char *ipstring;
	int i, r_slot;
	int serverPort;

	crDebug("Replicate SPU: Enter replicatespuReplicate(ipaddress=0x%x)", ipaddress);

	replicatespuFlushAll( (void *)thread );

#ifdef CHROMIUM_THREADSAFE_notyet
	crLockMutex(&_ReplicateMutex);
#endif

	/*
	 * Find empty slot.
	 * Slot 0 is the dummy slot (a non-existant server on devnull connection)
	 */
	for (r_slot = 1; r_slot < CR_MAX_REPLICANTS; r_slot++) {
		if (!IS_CONNECTED(replicate_spu.rserver[r_slot].conn))
			break;
	}
	if (r_slot == CR_MAX_REPLICANTS) {
		crWarning("Replicate SPU: no more replicant slots available");
		return;
	}

	/**
	 ** OK, now rserver[r_slot] is free for use.
	 **/

	/*
	 * At this time, we can only support one VNC viewer per host.
	 * Check for that here.
	 */
	for (i = 1; i < CR_MAX_REPLICANTS; i++) {
		if (replicate_spu.ipnumbers[i] == ipaddress) {
			CRConnection *conn = replicate_spu.rserver[i].conn;
			/* If the connection appears to be active, it may actually be a dangling
			 * connection.  Try flushing it now.  If flushing fails, the connection
			 * type will definitely be CR_NO_CONNECTION (which we test below).
			 */
			if (conn) {
				if (conn->type != CR_NO_CONNECTION) {
					FlushConnection(i);
				}
				if (conn->type != CR_NO_CONNECTION) {
					crWarning("Replicate SPU: Can't connect to multiple VNC viewers on one host.");
#if 0
					/* The above test isn't 100% reliable and can prevent successful
					 * restart of a viewer on a host.  For now, just print warning and
					 * continue.
					 */
					return;
#endif
				}
			}
		}
	}

	replicate_spu.ipnumbers[r_slot] = ipaddress;

	serverPort = replicate_spu.chromium_start_port + r_slot;

	if (replicate_spu.vncAvailable) {
		/* Send a ChromiumStart message to the VNC Server.  The VNC Server will
		 * in turn send a ChromiumStart message to all the attached VNC viewers.
		 * The VNC Viewer/Chromium module will tell its crserver that there's
		 * a new OpenGL client.
		 * We pass the mothership port and crserver port in this message.
		 */
		char protocol[100], hostname[1000];
		const char *mothershipURL;
		unsigned short mothershipPort;
		mothershipURL = crGetenv("CRMOTHERSHIP");
		crDebug("Replicate SPU: CRMOTHERSHIP env var = %s", mothershipURL);
		if (mothershipURL)
			crParseURL(mothershipURL, protocol, hostname, &mothershipPort,
								 DEFAULT_MOTHERSHIP_PORT);
		else
			mothershipPort = DEFAULT_MOTHERSHIP_PORT;
		crDebug("Replicate SPU: Sending ChromiumStart msg to VNC server, port=%d",
						serverPort);

		if (!XVncChromiumStart(replicate_spu.glx_display, ipaddress,
													 serverPort, mothershipPort)) {
			 crWarning("Replicate SPU: XVncChromiumStart() call failed");
		}
	}

	addr.s_addr = ipaddress;
	ipstring = inet_ntoa(addr);
	hosturl = crAlloc(crStrlen(ipstring) + 9);
	sprintf(hosturl, "tcpip://%s", ipstring);

	crDebug("Replicate SPU attaching to %s on port %d", hosturl, serverPort);

	/* connect to the remote VNC server */
	replicate_spu.rserver[r_slot].name = crStrdup( replicate_spu.name );
	replicate_spu.rserver[r_slot].buffer_size = replicate_spu.buffer_size;
	replicate_spu.rserver[r_slot].conn
		= crNetConnectToServer( hosturl, serverPort,
														replicate_spu.rserver[r_slot].buffer_size, 1);

	if (!replicate_spu.rserver[r_slot].conn) {
		crWarning("Replicate SPU: failed to connect to %s", hosturl);
		return;
	}

	CRASSERT(replicate_spu.rserver[r_slot].conn);

	/*
	 * Setup the the packer flush function.  While replicating state to
	 * a particular server we definitely don't want to do any broadcast
	 * flushing!
	 */
	crPackFlushFunc( thread->packer, replicatespuFlushOnePacker );
	crPackSendHugeFunc( thread->packer, replicatespuHugeOnePacker );

	NewServerIndex = r_slot;

	/*
	 * Create server-side windows and contexts by walking tables of app windows
	 * and contexts.  Note that windows can be created in random order,
	 * but contexts must be created in the order they were originally
	 * created, or shared contexts will break.
	 */
	crHashtableWalk(replicate_spu.windowTable, replicatespuReplicateWindow, thread);
	crListApply(replicate_spu.contextList, replicatespuReplicateContext, thread);

	/* MakeCurrent, the current context */
	if (thread->currentContext) {
		int serverWindow = thread->currentContext->currentWindow->id[r_slot];
		int serverContext = thread->currentContext->rserverCtx[r_slot];
		if (replicate_spu.swap)
			crPackMakeCurrentSWAP(serverWindow, 0, serverContext);
	 	else
			crPackMakeCurrent(serverWindow, 0, serverContext);

		crStateMakeCurrent( thread->currentContext->State );
	}

	/*
	 * Set window sizes
	 */
	crHashtableWalk(replicate_spu.windowTable, replicatespuResizeWindows, thread);
	replicatespuFlushOne(thread, NewServerIndex);

	/*
	 * restore normal, broadcasting packer flush function now.
	 */
	crPackFlushFunc( thread->packer, replicatespuFlush );
	crPackSendHugeFunc( thread->packer, replicatespuHuge );

	NewServerIndex = -1;

	crDebug("Replicate SPU: leaving replicatespuReplicate");

#ifdef CHROMIUM_THREADSAFE_notyet
	crUnlockMutex(&_ReplicateMutex);
#endif
}