bool CNullModem::ServerConnect() {
	// check if a connection is available.
	clientsocket=serversocket->Accept();
	if (!clientsocket) return false;
	
	Bit8u peeripbuf[16];
	clientsocket->GetRemoteAddressString(peeripbuf);
	LOG_MSG("Serial%d: A client (%s) has connected.",(int)COMNUMBER,peeripbuf);
#if SERIAL_DEBUG
	log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf);
#endif

    /* FIXME: It would be nice if the SDL net library had a bind() call to bind only to a specific interface.
     *        Or maybe it does... what am I missing? */
    if (!nonlocal && strcmp((char*)peeripbuf,"127.0.0.1") != 0) {
        LOG_MSG("Serial%d: Non-localhost client (%s) dropped by nonlocal:0 policy. To accept connections from network, set nonlocal:1",(int)COMNUMBER,peeripbuf);
        delete clientsocket;
        clientsocket = NULL;
        return false;
    }

	clientsocket->SetSendBufferSize(256);
	rx_state=N_RX_IDLE;
	setEvent(SERIAL_POLLING_EVENT, 1);
	
	// we don't accept further connections
	delete serversocket;
	serversocket=0;

	// transmit the line status
	setRTSDTR(getRTS(), getDTR());
	if (transparent) setCD(true);
	return true;
}
Exemple #2
0
void CSerialDummy::setDTR(bool val) {
#ifdef CHECKIT_TESTPLUG
	setDSR(val);
	setRI(val);
	setCD(val);
#endif
}
Exemple #3
0
void CDirectSerial::updateMSR () {
	int new_status = SERIAL_getmodemstatus(comport);

	setCTS(new_status&SERIAL_CTS? true:false);
	setDSR(new_status&SERIAL_DSR? true:false);
	setRI(new_status&SERIAL_RI? true:false);
	setCD(new_status&SERIAL_CD? true:false);
}
Exemple #4
0
CSerialDummy::CSerialDummy(Bitu id,	CommandLine* cmd):CSerial(id, cmd) {
	CSerial::Init_Registers();
	setRI(false);
	setDSR(false);
	setCD(false);
	setCTS(false);
	InstallationSuccessful=true;
}
CSerialLog::CSerialLog(Bitu id,	CommandLine* cmd):CSerial(id, cmd) {
	CSerial::Init_Registers();
	// DSR+CTS on to make sure the DOS COM device will not get stuck waiting for them
	setRI(false);
	setCD(false);
	setDSR(true);
	setCTS(true);
	InstallationSuccessful=true;
}
Exemple #6
0
bool CNullModem::ServerListen() {
	// Start the server listen port.
	serversocket = new TCPServerSocket(serverport);
	if (!serversocket->isopen) return false;
	LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...",
		COMNUMBER,serverport);
	setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
	setCD(false);
	return true;
}
Exemple #7
0
bool CNullModem::ClientConnect(TCPClientSocket* newsocket) {
	Bit8u peernamebuf[16];
	clientsocket = newsocket;
 
	if (!clientsocket->isopen) {
		LOG_MSG("Serial%d: Connection failed.",COMNUMBER);
		delete clientsocket;
		clientsocket=0;
		setCD(false);
		return false;
	}
	clientsocket->SetSendBufferSize(256);
	clientsocket->GetRemoteAddressString(peernamebuf);
	// transmit the line status
	if (!transparent) setRTSDTR(getRTS(), getDTR());
	rx_state=N_RX_IDLE;
	LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf);
	setEvent(SERIAL_POLLING_EVENT, 1);
	setCD(true);
	return true;
}
void CDirectSerial::updateMSR () {
	DWORD dptr = 0;

	if (!GetCommModemStatus (hCom, &dptr)) {
#ifdef SERIALPORT_DEBUGMSG
//		LOG_MSG ("Serial port at %x: GetCommModemStatus failed!", base);
#endif
		//return;
	}
	setCTS((dptr & MS_CTS_ON)!=0);
	setDSR((dptr & MS_DSR_ON)!=0);
	setRI ((dptr & MS_RING_ON)!=0);
	setCD((dptr & MS_RLSD_ON)!=0);
}
Exemple #9
0
void CNullModem::Disconnect() {
	removeEvent(SERIAL_POLLING_EVENT);
	removeEvent(SERIAL_RX_EVENT);
	// it was disconnected; free the socket and restart the server socket
	LOG_MSG("Serial%d: Disconnected.",COMNUMBER);
	delete clientsocket;
	clientsocket=0;
	setDSR(false);
	setCTS(false);
	setCD(false);
	
	if (serverport) {
		serversocket = new TCPServerSocket(serverport);
		if (serversocket->isopen) 
			setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
		else delete serversocket;
	} else if (dtrrespect) {
		setEvent(SERIAL_NULLMODEM_DTR_EVENT,50);
		DTR_delta = getDTR(); // try to reconnect the next time DTR is set
	}
}
Exemple #10
0
bool CNullModem::ServerConnect() {
	// check if a connection is available.
	clientsocket=serversocket->Accept();
	if (!clientsocket) return false;
	
	Bit8u peeripbuf[16];
	clientsocket->GetRemoteAddressString(peeripbuf);
	LOG_MSG("Serial%d: A client (%s) has connected.",COMNUMBER,peeripbuf);
#if SERIAL_DEBUG
	log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf);
#endif
	clientsocket->SetSendBufferSize(256);
	rx_state=N_RX_IDLE;
	setEvent(SERIAL_POLLING_EVENT, 1);
	
	// we don't accept further connections
	delete serversocket;
	serversocket=0;

	// transmit the line status
	setRTSDTR(getRTS(), getDTR());
	if (transparent) setCD(true);
	return true;
}
Exemple #11
0
bool ResourceManager::init() {
    uint32 i, j;

    // Until proven differently, assume we're on CD 1. This is so the start
    // dialog will be able to play any music at all.

    setCD(1);

    // We read in the resource info which tells us the names of the
    // resource cluster files ultimately, although there might be groups
    // within the clusters at this point it makes no difference. We only
    // wish to know what resource files there are and what is in each

    Common::File file;

    if (!file.open("resource.inf")) {
        GUIErrorMessage("Broken Sword II: Cannot open resource.inf");
        return false;
    }

    // The resource.inf file is a simple text file containing the names of
    // all the resource files.

    while (1) {
        char *buf = _resFiles[_totalClusters].fileName;
        uint len = sizeof(_resFiles[_totalClusters].fileName);

        if (!file.readLine(buf, len))
            break;

        int pos = strlen(buf);
        if (buf[pos - 1] == 0x0A)
            buf[pos - 1] = 0;

        _resFiles[_totalClusters].numEntries = -1;
        _resFiles[_totalClusters].entryTab = NULL;
        if (++_totalClusters >= MAX_res_files) {
            GUIErrorMessage("Broken Sword II: Too many entries in resource.inf");
            return false;
        }
    }

    file.close();

    // Now load in the binary id to res conversion table
    if (!file.open("resource.tab")) {
        GUIErrorMessage("Broken Sword II: Cannot open resource.tab");
        return false;
    }

    // Find how many resources
    uint32 size = file.size();

    _totalResFiles = size / 4;

    // Table seems ok so malloc some space
    _resConvTable = (uint16 *)malloc(size);

    for (i = 0; i < size / 2; i++)
        _resConvTable[i] = file.readUint16LE();

    if (file.eos() || file.err()) {
        file.close();
        GUIErrorMessage("Broken Sword II: Cannot read resource.tab");
        return false;
    }

    file.close();

    // Check that we have cd.inf file, unless we are running PSX
    // version, which has all files on one disc.

    if (!file.open("cd.inf") && !Sword2Engine::isPsx()) {
        GUIErrorMessage("Broken Sword II: Cannot open cd.inf");
        return false;
    }

    CdInf *cdInf = new CdInf[_totalClusters];

    for (i = 0; i < _totalClusters; i++) {

        if (Sword2Engine::isPsx()) { // We are running PSX version, artificially fill CdInf structure
            cdInf[i].cd = CD1;
        } else { // We are running PC version, read cd.inf file
            file.read(cdInf[i].clusterName, sizeof(cdInf[i].clusterName));

            cdInf[i].cd = file.readByte();

            if (file.eos() || file.err()) {
                delete[] cdInf;
                file.close();
                GUIErrorMessage("Broken Sword II: Cannot read cd.inf");
                return false;
            }

        }

        // It has been reported that there are two different versions
        // of the cd.inf file: One where all clusters on CD also have
        // the LOCAL_CACHE bit set. This bit is no longer used. To
        // avoid future problems, let's normalize the flag once and for
        // all here.

        if (cdInf[i].cd & LOCAL_PERM)
            cdInf[i].cd = 0;
        else if (cdInf[i].cd & CD1)
            cdInf[i].cd = 1;
        else if (cdInf[i].cd & CD2)
            cdInf[i].cd = 2;
        else
            cdInf[i].cd = 0;

        // Any file on "CD 0" may be needed at all times. Verify that
        // it exists. Any other missing cluster will be requested with
        // an "insert CD" message. Of course, the file may still vanish
        // during game-play (oh, that wascally wabbit!) in which case
        // the resource manager will print a fatal error.

        if (cdInf[i].cd == 0 && !Common::File::exists((char *)cdInf[i].clusterName)) {
            GUIErrorMessage("Broken Sword II: Cannot find " + Common::String((char *)cdInf[i].clusterName));
            delete[] cdInf;
            return false;
        }
    }

    file.close();

    // We check the presence of resource files in cd.inf
    // This is ok in PC version, but in PSX version we don't
    // have cd.inf so we'll have to skip this.
    if (!Sword2Engine::isPsx()) {
        for (i = 0; i < _totalClusters; i++) {
            for (j = 0; j < _totalClusters; j++) {
                if (scumm_stricmp((char *)cdInf[j].clusterName, _resFiles[i].fileName) == 0)
                    break;
            }

            if (j == _totalClusters) {
                delete[] cdInf;
                GUIErrorMessage(Common::String(_resFiles[i].fileName) + " is not in cd.inf");
                return false;
            }

            _resFiles[i].cd = cdInf[j].cd;
        }
    }

    delete[] cdInf;

    debug(1, "%d resources in %d cluster files", _totalResFiles, _totalClusters);
    for (i = 0; i < _totalClusters; i++)
        debug(2, "filename of cluster %d: -%s (%d)", i, _resFiles[i].fileName, _resFiles[i].cd);

    _resList = (Resource *)malloc(_totalResFiles * sizeof(Resource));

    for (i = 0; i < _totalResFiles; i++) {
        _resList[i].ptr = NULL;
        _resList[i].size = 0;
        _resList[i].refCount = 0;
        _resList[i].prev = _resList[i].next = NULL;
    }

    return true;
}
Exemple #12
0
/**
 * Returns the address of a resource. Loads if not in memory. Retains a count.
 */
byte *ResourceManager::openResource(uint32 res, bool dump) {
    assert(res < _totalResFiles);


    // FIXME: In PSX edition, not all top menu icons are present (TOP menu is not used).
    // Though, at present state, the engine still ask for the resources.
    if (Sword2Engine::isPsx()) { // We need to "rewire" missing icons
        if (res == 342) res = 364; // Rewire RESTORE ICON to SAVE ICON
    }

    // Is the resource in memory already? If not, load it.

    if (!_resList[res].ptr) {
        // Fetch the correct file and read in the correct portion.
        uint16 cluFileNum = _resConvTable[res * 2]; // points to the number of the ascii filename

        assert(cluFileNum != 0xffff);

        // Relative resource within the file
        // First we have to find the file via the _resConvTable
        uint16 actual_res = _resConvTable[(res * 2) + 1];

        debug(5, "openResource %s res %d", _resFiles[cluFileNum].fileName, res);

        // If we're loading a cluster that's only available from one
        // of the CDs, remember which one so that we can play the
        // correct speech and music.

        if (Sword2Engine::isPsx()) // We have only one disk in PSX version
            setCD(CD1);
        else
            setCD(_resFiles[cluFileNum].cd);

        // Actually, as long as the file can be found we don't really
        // care which CD it's on. But if we can't find it, keep asking
        // for the CD until we do.

        Common::File *file = openCluFile(cluFileNum);

        if (_resFiles[cluFileNum].entryTab == NULL) {
            // we didn't read from this file before, get its index table
            readCluIndex(cluFileNum, file);
        }

        assert(_resFiles[cluFileNum].entryTab);

        uint32 pos = _resFiles[cluFileNum].entryTab[actual_res * 2 + 0];
        uint32 len = _resFiles[cluFileNum].entryTab[actual_res * 2 + 1];

        file->seek(pos, SEEK_SET);

        debug(6, "res len %d", len);

        // Ok, we know the length so try and allocate the memory.
        _resList[res].ptr = _vm->_memory->memAlloc(len, res);
        _resList[res].size = len;
        _resList[res].refCount = 0;

        file->read(_resList[res].ptr, len);

        debug(3, "Loaded resource '%s' (%d) from '%s' on CD %d (%d)", fetchName(_resList[res].ptr), res, _resFiles[cluFileNum].fileName, getCD(), _resFiles[cluFileNum].cd);

        if (dump) {
            char buf[256];
            const char *tag;

            switch (fetchType(_resList[res].ptr)) {
            case ANIMATION_FILE:
                tag = "anim";
                break;
            case SCREEN_FILE:
                tag = "layer";
                break;
            case GAME_OBJECT:
                tag = "object";
                break;
            case WALK_GRID_FILE:
                tag = "walkgrid";
                break;
            case GLOBAL_VAR_FILE:
                tag = "globals";
                break;
            case PARALLAX_FILE_null:
                tag = "parallax";	// Not used!
                break;
            case RUN_LIST:
                tag = "runlist";
                break;
            case TEXT_FILE:
                tag = "text";
                break;
            case SCREEN_MANAGER:
                tag = "screen";
                break;
            case MOUSE_FILE:
                tag = "mouse";
                break;
            case WAV_FILE:
                tag = "wav";
                break;
            case ICON_FILE:
                tag = "icon";
                break;
            case PALETTE_FILE:
                tag = "palette";
                break;
            default:
                tag = "unknown";
                break;
            }

            sprintf(buf, "dumps/%s-%d.dmp", tag, res);

            if (!Common::File::exists(buf)) {
                Common::DumpFile out;
                if (out.open(buf))
                    out.write(_resList[res].ptr, len);
            }
        }

        // close the cluster
        file->close();
        delete file;

        _usedMem += len;
        checkMemUsage();
    } else if (_resList[res].refCount == 0)
        removeFromCacheList(_resList + res);

    _resList[res].refCount++;

    return _resList[res].ptr;
}
void CSerialLog::setDTR(bool val) {
	setDSR(val);
	setRI(val);
	setCD(val);
}
Exemple #14
0
CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
	Bitu temptcpport=23;
	memset(&telClient, 0, sizeof(telClient));
	InstallationSuccessful = false;
	serversocket = 0;
	clientsocket = 0;
	serverport = 0;
	clientport = 0;

	rx_retry = 0;
	rx_retry_max = 20;
	rx_state=N_RX_DISC;

	tx_gather = 12;
	
	dtrrespect=false;
	tx_block=false;
	receiveblock=false;
	transparent=false;
	telnet=false;
	
	Bitu bool_temp=0;

	// usedtr: The nullmodem will
	// 1) when it is client connect to the server not immediately but
	//    as soon as a modem-aware application is started (DTR is switched on).
	// 2) only receive data when DTR is on.
	if (getBituSubstring("usedtr:", &bool_temp, cmd)) {
		if (bool_temp==1) {
			dtrrespect=true;
			transparent=true;
			DTR_delta=false; // connect immediately when DTR is already 1
		}
	}
	// transparent: don't add additional handshake control.
	if (getBituSubstring("transparent:", &bool_temp, cmd)) {
		if (bool_temp==1) transparent=true;
		else transparent=false;
	}
	// telnet: interpret telnet commands.
	if (getBituSubstring("telnet:", &bool_temp, cmd)) {
		if (bool_temp==1) {
			transparent=true;
			telnet=true;
		}
	}
	// rxdelay: How many milliseconds to wait before causing an
	// overflow when the application is unresponsive.
	if (getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {
		if (!(rx_retry_max<=10000)) {
			rx_retry_max=50;
		}
	}
	// txdelay: How many milliseconds to wait before sending data.
	// This reduces network overhead quite a lot.
	if (getBituSubstring("txdelay:", &tx_gather, cmd)) {
		if (!(tx_gather<=500)) {
			tx_gather=12;
		}
	}
	// port is for both server and client
	if (getBituSubstring("port:", &temptcpport, cmd)) {
		if (!(temptcpport>0&&temptcpport<65536)) {
			temptcpport=23;
		}
	}
	// socket inheritance (client-alike)
	if (getBituSubstring("inhsocket:", &bool_temp, cmd)) {
#ifdef NATIVESOCKETS
		if (Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) {
			if (bool_temp==1) {
				int sock;
				if (control->cmdline->FindInt("-socket",sock,true)) {
					dtrrespect=false;
					transparent=true;
					LOG_MSG("Inheritance socket handle: %d",sock);
					if (!ClientConnect(new TCPClientSocket(sock)))
						return;
				} else {
					LOG_MSG("Serial%d: -socket parameter missing.",COMNUMBER);
					return;
				}
			}
		} else {
			LOG_MSG("Serial%d: socket inheritance not supported on this platform.",
				COMNUMBER);
			return;
		}
#else
		LOG_MSG("Serial%d: socket inheritance not available.", COMNUMBER);
#endif
	} else {
		// normal server/client
		std::string tmpstring;
		if (cmd->FindStringBegin("server:",tmpstring,false)) {
			// we are a client
			const char* hostnamechar=tmpstring.c_str();
			size_t hostlen=strlen(hostnamechar)+1;
			if (hostlen>sizeof(hostnamebuffer)) {
				hostlen=sizeof(hostnamebuffer);
				hostnamebuffer[sizeof(hostnamebuffer)-1]=0;
			}
			memcpy(hostnamebuffer,hostnamechar,hostlen);
			clientport=(Bit16u)temptcpport;
			if (dtrrespect) {
				// we connect as soon as DTR is switched on
				setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50);
				LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER);
			} else if (!ClientConnect(
				new TCPClientSocket((char*)hostnamebuffer,(Bit16u)clientport)))
				return;
		} else {
			// we are a server
			serverport = (Bit16u)temptcpport;
			if (!ServerListen()) return;
		}
	}
	CSerial::Init_Registers();
	InstallationSuccessful = true;

	setCTS(dtrrespect||transparent);
	setDSR(dtrrespect||transparent);
	setRI(false);
	setCD(clientsocket > 0); // CD on if connection established
}