net_ser.c

来自「quake1 dos源代码最新版本」· C语言 代码 · 共 952 行 · 第 1/2 页

C
952
字号
	sock->sendMessageLength = message->cursize;
	sock->lastSendTime = net_time;

	return 1;
}


static void ReSendMessage (qsocket_t *sock)
{
	sizebuf_t	temp;

	Con_DPrintf("Serial: re-sending reliable\n");
	temp.data = sock->sendMessage;
	temp.maxsize = sock->sendMessageLength;
	temp.cursize = sock->sendMessageLength;
	Serial_SendMessage (sock, &temp);
}


int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message)
{
	SerialLine *p;
	int n;
	unsigned short crc;
	byte b;

	p = (SerialLine *)sock->driverdata;

	if (!TTY_OutputQueueIsEmpty(p->tty))
	{
		TTY_Flush(p->tty);
		return 1;
	}

	CRC_Init (&crc);

	// message type
	b = MTYPE_UNRELIABLE;
	if (p->client)
		b |= MTYPE_CLIENT;
	TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// sequence
	b = p->sock->unreliableSendSequence;
	p->sock->unreliableSendSequence = (b + 1) & 0xff;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// data length
	b = message->cursize >> 8;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);
	b = message->cursize & 0xff;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// data
	for (n = 0; n < message->cursize; n++)
	{
		b = message->data[n];
		TTY_WriteByte(p->tty, b);
		if (b == ESCAPE_COMMAND)
			TTY_WriteByte(p->tty, b);
		CRC_ProcessByte (&crc, b);
	}

	// checksum
	b = CRC_Value (crc) >> 8;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	b = CRC_Value (crc) & 0xff;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);

	// end of message
	TTY_WriteByte(p->tty, ESCAPE_COMMAND);
	TTY_WriteByte(p->tty, ESCAPE_EOM);

	TTY_Flush(p->tty);

	return 1;
}


static void Serial_SendACK (SerialLine *p, byte sequence)
{
	unsigned short crc;
	byte b;

	CRC_Init (&crc);

	// message type
	b = MTYPE_ACK;
	if (p->client)
		b |= MTYPE_CLIENT;
	TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// sequence
	b = sequence;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// checksum
	b = CRC_Value (crc) >> 8;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	b = CRC_Value (crc) & 0xff;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);

	// end of message
	TTY_WriteByte(p->tty, ESCAPE_COMMAND);
	TTY_WriteByte(p->tty, ESCAPE_EOM);

	TTY_Flush(p->tty);
}


static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message)
{
	unsigned short crc;
	int n;
	byte b;

	CRC_Init (&crc);

	// message type
	b = MTYPE_CONTROL;
	if (p->client)
		b |= MTYPE_CLIENT;
	TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// data length
	b = message->cursize >> 8;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);
	b = message->cursize & 0xff;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	CRC_ProcessByte (&crc, b);

	// data
	for (n = 0; n < message->cursize; n++)
	{
		b = message->data[n];
		TTY_WriteByte(p->tty, b);
		if (b == ESCAPE_COMMAND)
			TTY_WriteByte(p->tty, b);
		CRC_ProcessByte (&crc, b);
	}

	// checksum
	b = CRC_Value (crc) >> 8;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);
	b = CRC_Value (crc) & 0xff;
	TTY_WriteByte(p->tty, b);
	if (b == ESCAPE_COMMAND)
		TTY_WriteByte(p->tty, b);

	// end of message
	TTY_WriteByte(p->tty, ESCAPE_COMMAND);
	TTY_WriteByte(p->tty, ESCAPE_EOM);

	TTY_Flush(p->tty);
}


static int _Serial_GetMessage (SerialLine *p)
{
	byte	ret;
	short	length;

	if (ProcessInQueue(p))
		return -1;

	if (p->sock->receiveMessageLength == 0)
		return 0;

	ret = p->sock->receiveMessage[0];
	length = *(short *)&p->sock->receiveMessage[1];
	if (ret == MTYPE_CONTROL)
		ret = 1;

	SZ_Clear (&net_message);
	SZ_Write (&net_message, &p->sock->receiveMessage[3], length);

	length += 3;
	p->sock->receiveMessageLength -= length;

	if (p->sock->receiveMessageLength + p->lengthFound)
		Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound);

	return ret;
}

int Serial_GetMessage (qsocket_t *sock)
{
	SerialLine *p;
	int		ret;

	p = (SerialLine *)sock->driverdata;

	ret = _Serial_GetMessage (p);

	if (ret == 1)
		messagesReceived++;

	if (!sock->canSend)
		if ((net_time - sock->lastSendTime) > 1.0)
		{
			ReSendMessage (sock);
			sock->lastSendTime = net_time;
		}

	return ret;
}


void Serial_Close (qsocket_t *sock)
{
	SerialLine *p = (SerialLine *)sock->driverdata;
	TTY_Close(p->tty);
	ResetSerialLineProtocol (p);
}


char *com_types[] = {"direct", "modem"};
unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600};

void Serial_SearchForHosts (qboolean xmit)
{
	int		n;
	SerialLine *p;

	if (sv.active)
		return;

	if (hostCacheCount == HOSTCACHESIZE)
		return;

	// see if we've already answered
	for (n = 0; n < hostCacheCount; n++)
		if (strcmp (hostcache[n].cname, "#") == 0)
			return;

	for (n = 0; n < NUM_COM_PORTS; n++)
		if (TTY_IsEnabled(n))
			break;
	if (n == NUM_COM_PORTS)
		return;
	p = &serialLine[n];

	if (TTY_IsModem(p->tty))
		return;

	sprintf(hostcache[hostCacheCount].name, "COM%u", n+1);
	strcpy(hostcache[hostCacheCount].map, "");
	hostcache[hostCacheCount].users = 0;
	hostcache[hostCacheCount].maxusers = 0;
	hostcache[hostCacheCount].driver = net_driverlevel;
	strcpy(hostcache[hostCacheCount].cname, "#");
	hostCacheCount++;

	return;
}


static qsocket_t *_Serial_Connect (char *host, SerialLine *p)
{
	int		ret;
	double	start_time;
	double	last_time;

	p->client = true;
	if (TTY_Connect(p->tty, host))
		return NULL;

	p->sock = NET_NewQSocket ();
	p->sock->driver = myDriverLevel;
	if (p->sock == NULL)
	{
		Con_Printf("No sockets available\n");
		return NULL;
	}
	p->sock->driverdata = p;

	// send the connection request
	start_time = SetNetTime();
	last_time = 0.0;

	SZ_Clear(&net_message);
	MSG_WriteByte(&net_message, CCREQ_CONNECT);
	MSG_WriteString(&net_message, "QUAKE");
	do
	{
		SetNetTime();
		if ((net_time - last_time) >= 1.0)
		{
			Serial_SendControlMessage (p, &net_message);
			last_time = net_time;
			Con_Printf("trying...\n"); SCR_UpdateScreen ();
		}
		ret = _Serial_GetMessage (p);
	}
	while (ret == 0 && (net_time - start_time) < 5.0);

	if (ret == 0)
	{
		Con_Printf("Unable to connect, no response\n");
		goto ErrorReturn;
	}

	if (ret == -1)
	{
		Con_Printf("Connection request error\n");
		goto ErrorReturn;
	}

	MSG_BeginReading ();
	ret = MSG_ReadByte();
	if (ret == CCREP_REJECT)
	{
		Con_Printf(MSG_ReadString());
		goto ErrorReturn;
	}
	if (ret != CCREP_ACCEPT)
	{
		Con_Printf("Unknown connection response\n");
		goto ErrorReturn;
	}

	p->connected = true;
	p->sock->lastMessageTime = net_time;

	Con_Printf ("Connection accepted\n");

	return p->sock;

ErrorReturn:
	TTY_Disconnect(p->tty);
	return NULL;
}

qsocket_t *Serial_Connect (char *host)
{
	int			n;
	qsocket_t	*ret = NULL;

	// see if this looks like a phone number
	if (*host == '#')
		host++;
	for (n = 0; n < strlen(host); n++)
		if (host[n] == '.' || host[n] == ':')
			return NULL;

	for (n = 0; n < NUM_COM_PORTS; n++)
		if (TTY_IsEnabled(n) && !serialLine[n].connected)
			if ((ret = _Serial_Connect (host, &serialLine[n])))
				break;
	return ret;
}


static qsocket_t *_Serial_CheckNewConnections (SerialLine *p)
{
	int	command;

	p->client = false;
	if (!TTY_CheckForConnection(p->tty))
		return NULL;

	if (TTY_IsModem(p->tty))
	{
		if (!p->connecting)
		{
			p->connecting = true;
			p->connect_time = net_time;
		}
		else if ((net_time - p->connect_time) > 15.0)
		{
			p->connecting = false;
			TTY_Disconnect(p->tty);
			return NULL;
		}
	}

	p->sock = NET_NewQSocket ();
	p->sock->driver = myDriverLevel;
	if (p->sock == NULL)
	{
		Con_Printf("No sockets available\n");
		return NULL;
	}
	p->sock->driverdata = p;

	SZ_Clear(&net_message);
	if (_Serial_GetMessage(p) != 1)
	{
		NET_FreeQSocket(p->sock);
		return NULL;
	}

	MSG_BeginReading ();
	command = MSG_ReadByte();

	if (command == CCREQ_SERVER_INFO)
	{
		if (strcmp(MSG_ReadString(), "QUAKE") != 0)
			return NULL;

		if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION)
			return NULL;

		SZ_Clear(&net_message);
		MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
		MSG_WriteString(&net_message, hostname->string);
		MSG_WriteString(&net_message, sv.name);
		MSG_WriteByte(&net_message, net_activeconnections);
		MSG_WriteByte(&net_message, svs.maxclients);
		Serial_SendControlMessage (p, &net_message);
		SZ_Clear(&net_message);
		return NULL;
	}

	if (command != CCREQ_CONNECT)
		return NULL;

	if (strcmp(MSG_ReadString(), "QUAKE") != 0)
		return NULL;

	// send him back the info about the server connection he has been allocated
	SZ_Clear(&net_message);
	MSG_WriteByte(&net_message, CCREP_ACCEPT);
	Serial_SendControlMessage (p, &net_message);
	SZ_Clear(&net_message);

	p->connected = true;
	p->connecting = false;
	p->sock->lastMessageTime = net_time;
	sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1));

	return p->sock;
}

qsocket_t *Serial_CheckNewConnections (void)
{
	int			n;
	qsocket_t	*ret = NULL;

	for (n = 0; n < NUM_COM_PORTS; n++)
		if (TTY_IsEnabled(n) && !serialLine[n].connected)
			if ((ret = _Serial_CheckNewConnections (&serialLine[n])))
				break;
	return ret;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?