1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 // net_ser.c 21 22 #include "quakedef.h" 23 #include "net_ser.h" 24 #include "dosisms.h" 25 #include "crc.h" 26 27 #include "net_comx.c" 28 29 // serial protocol 30 31 #define SERIAL_PROTOCOL_VERSION 3 32 33 // The serial protocol is message oriented. The high level message format is 34 // a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All 35 // multi-byte fields are sent in network byte order. There are currently 4 36 // MTYPEs defined. Their formats are as follows: 37 // 38 // MTYPE_RELIABLE sequence data_length data checksum eom 39 // MTYPE_UNRELIABLE sequence data_length data checksum eom 40 // MTYPE_ACK sequence checksum eom 41 // MTYPE_CONTROL data_length data checksum eom 42 // 43 // sequence is an 8-bit unsigned value starting from 0 44 // data_length is a 16-bit unsigned value; it is the length of the data only 45 // the checksum is a 16-bit value. the CRC formula used is defined in crc.h. 46 // the checksum covers the entire messages, excluding itself 47 // eom is a special 2 byte sequence used to mark the End Of Message. This is 48 // needed for error recovery. 49 // 50 // A lot of behavior is based on knowledge of the upper level Quake network 51 // layer. For example, only one reliable message can be outstanding (pending 52 // reception of an MTYPE_ACK) at a time. 53 // 54 // The low level routines used to communicate with the modem are not part of 55 // this protocol. 56 // 57 // The CONTROL messages are only used for session establishment. They are 58 // not reliable or sequenced. 59 60 #define MTYPE_RELIABLE 0x01 61 #define MTYPE_UNRELIABLE 0x02 62 #define MTYPE_CONTROL 0x03 63 #define MTYPE_ACK 0x04 64 #define MTYPE_CLIENT 0x80 65 66 #define ESCAPE_COMMAND 0xe0 67 #define ESCAPE_EOM 0x19 68 69 static qboolean listening = false; 70 71 72 typedef struct SerialLine_s 73 { 74 struct SerialLine_s *next; 75 qsocket_t *sock; 76 int lengthStated; 77 int lengthFound; 78 int tty; 79 qboolean connected; 80 qboolean connecting; 81 qboolean client; 82 double connect_time; 83 unsigned short crcStated; 84 unsigned short crcValue; 85 byte currState; 86 byte prevState; 87 byte mtype; 88 byte sequence; 89 } SerialLine; 90 91 #define STATE_READY 0 92 #define STATE_SEQUENCE 1 93 #define STATE_LENGTH1 2 94 #define STATE_LENGTH2 3 95 #define STATE_DATA 4 96 #define STATE_CRC1 5 97 #define STATE_CRC2 6 98 #define STATE_EOM 7 99 #define STATE_ESCAPE 8 100 #define STATE_ABORT 9 101 102 SerialLine serialLine[NUM_COM_PORTS]; 103 104 int myDriverLevel; 105 106 static void Serial_SendACK (SerialLine *p, byte sequence); 107 108 109 static void ResetSerialLineProtocol (SerialLine *p) 110 { 111 p->connected = false; 112 p->connecting = false; 113 p->currState = STATE_READY; 114 p->prevState = STATE_READY; 115 p->lengthFound = 0; 116 } 117 118 119 static int ProcessInQueue(SerialLine *p) 120 { 121 int b; 122 123 while (1) 124 { 125 b = TTY_ReadByte(p->tty); 126 if (b == ERR_TTY_NODATA) 127 break; 128 129 if (b == ERR_TTY_LINE_STATUS) 130 { 131 p->currState = STATE_ABORT; 132 continue; 133 } 134 if (b == ERR_TTY_MODEM_STATUS) 135 { 136 p->currState = STATE_ABORT; 137 return -1; 138 } 139 140 if (b == ESCAPE_COMMAND) 141 if (p->currState != STATE_ESCAPE) 142 { 143 p->prevState = p->currState; 144 p->currState = STATE_ESCAPE; 145 continue; 146 } 147 148 if (p->currState == STATE_ESCAPE) 149 { 150 if (b == ESCAPE_EOM) 151 { 152 if (p->prevState == STATE_ABORT) 153 { 154 p->currState = STATE_READY; 155 p->lengthFound = 0; 156 continue; 157 } 158 159 if (p->prevState != STATE_EOM) 160 { 161 p->currState = STATE_READY; 162 p->lengthFound = 0; 163 Con_DPrintf("Serial: premature EOM\n"); 164 continue; 165 } 166 167 switch (p->mtype) 168 { 169 case MTYPE_RELIABLE: 170 Con_DPrintf("Serial: sending ack %u\n", p->sequence); 171 Serial_SendACK (p, p->sequence); 172 if (p->sequence == p->sock->receiveSequence) 173 { 174 p->sock->receiveSequence = (p->sequence + 1) & 0xff; 175 p->sock->receiveMessageLength += p->lengthFound; 176 } 177 else 178 Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence); 179 break; 180 181 case MTYPE_UNRELIABLE: 182 p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff; 183 p->sock->receiveMessageLength += p->lengthFound; 184 break; 185 186 case MTYPE_ACK: 187 Con_DPrintf("Serial: got ack %u\n", p->sequence); 188 if (p->sequence == p->sock->sendSequence) 189 { 190 p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff; 191 p->sock->canSend = true; 192 } 193 else 194 Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence); 195 break; 196 197 case MTYPE_CONTROL: 198 p->sock->receiveMessageLength += p->lengthFound; 199 break; 200 } 201 202 p->currState = STATE_READY; 203 p->lengthFound = 0; 204 continue; 205 } 206 207 208 if (b != ESCAPE_COMMAND) 209 { 210 p->currState = STATE_ABORT; 211 Con_DPrintf("Serial: Bad escape sequence\n"); 212 continue; 213 } 214 215 // b == ESCAPE_COMMAND 216 p->currState = p->prevState; 217 } 218 219 p->prevState = p->currState; 220 221 //DEBUG 222 if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE) 223 { 224 Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound); 225 p->currState = STATE_ABORT; 226 } 227 if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE) 228 { 229 Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound); 230 p->currState = STATE_ABORT; 231 } 232 //end DEBUG 233 234 switch (p->currState) 235 { 236 case STATE_READY: 237 CRC_Init(&p->crcValue); 238 CRC_ProcessByte(&p->crcValue, b); 239 if (p->client) 240 { 241 if ((b & MTYPE_CLIENT) != 0) 242 { 243 p->currState = STATE_ABORT; 244 Con_DPrintf("Serial: client got own message\n"); 245 break; 246 } 247 } 248 else 249 { 250 if ((b & MTYPE_CLIENT) == 0) 251 { 252 p->currState = STATE_ABORT; 253 Con_DPrintf("Serial: server got own message\n"); 254 break; 255 } 256 b &= 0x7f; 257 } 258 p->mtype = b; 259 if (b != MTYPE_CONTROL) 260 p->currState = STATE_SEQUENCE; 261 else 262 p->currState = STATE_LENGTH1; 263 if (p->mtype < MTYPE_ACK) 264 { 265 p->sock->receiveMessage[p->sock->receiveMessageLength] = b; 266 p->lengthFound++; 267 } 268 break; 269 270 case STATE_SEQUENCE: 271 p->sequence = b; 272 CRC_ProcessByte(&p->crcValue, b); 273 if (p->mtype != MTYPE_ACK) 274 p->currState = STATE_LENGTH1; 275 else 276 p->currState = STATE_CRC1; 277 break; 278 279 case STATE_LENGTH1: 280 p->lengthStated = b * 256; 281 CRC_ProcessByte(&p->crcValue, b); 282 p->currState = STATE_LENGTH2; 283 break; 284 285 case STATE_LENGTH2: 286 p->lengthStated += b; 287 CRC_ProcessByte(&p->crcValue, b); 288 if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN) 289 { 290 p->currState = STATE_ABORT; 291 Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated); 292 } 293 else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM) 294 { 295 p->currState = STATE_ABORT; 296 Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated); 297 } 298 else 299 { 300 p->currState = STATE_DATA; 301 if (p->mtype < MTYPE_ACK) 302 { 303 *(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated; 304 p->lengthFound += 2; 305 } 306 } 307 break; 308 309 case STATE_DATA: 310 p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b; 311 p->lengthFound++; 312 CRC_ProcessByte(&p->crcValue, b); 313 if (p->lengthFound == p->lengthStated + 3) 314 p->currState = STATE_CRC1; 315 break; 316 317 case STATE_CRC1: 318 p->crcStated = b * 256; 319 p->currState = STATE_CRC2; 320 break; 321 322 case STATE_CRC2: 323 p->crcStated += b; 324 if (p->crcStated == CRC_Value(p->crcValue)) 325 { 326 p->currState = STATE_EOM; 327 } 328 else 329 { 330 p->currState = STATE_ABORT; 331 Con_DPrintf("Serial: Bad crc\n"); 332 } 333 break; 334 335 case STATE_EOM: 336 p->currState = STATE_ABORT; 337 Con_DPrintf("Serial: Bad message format\n"); 338 break; 339 340 case STATE_ABORT: 341 break; 342 } 343 } 344 return 0; 345 } 346 347 348 int Serial_Init (void) 349 { 350 int n; 351 352 // LATER do Win32 serial support 353 #ifdef _WIN32 354 return -1; 355 #endif 356 357 if (COM_CheckParm("-nolan")) 358 return -1; 359 if (COM_CheckParm ("-noserial")) 360 return -1; 361 362 myDriverLevel = net_driverlevel; 363 364 if (TTY_Init()) 365 return -1; 366 367 for (n = 0; n < NUM_COM_PORTS; n++) 368 { 369 serialLine[n].tty = TTY_Open(n); 370 ResetSerialLineProtocol (&serialLine[n]); 371 } 372 373 Con_Printf("Serial driver initialized\n"); 374 serialAvailable = true; 375 376 return 0; 377 } 378 379 380 void Serial_Shutdown (void) 381 { 382 int n; 383 384 for (n = 0; n < NUM_COM_PORTS; n++) 385 { 386 if (serialLine[n].connected) 387 Serial_Close(serialLine[n].sock); 388 } 389 390 TTY_Shutdown(); 391 } 392 393 394 void Serial_Listen (qboolean state) 395 { 396 listening = state; 397 } 398 399 400 qboolean Serial_CanSendMessage (qsocket_t *sock) 401 { 402 return sock->canSend; 403 } 404 405 406 qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock) 407 { 408 return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty); 409 } 410 411 412 int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message) 413 { 414 SerialLine *p; 415 int n; 416 unsigned short crc; 417 byte b; 418 419 p = (SerialLine *)sock->driverdata; 420 CRC_Init (&crc); 421 422 // message type 423 b = MTYPE_RELIABLE; 424 if (p->client) 425 b |= MTYPE_CLIENT; 426 TTY_WriteByte(p->tty, b); 427 CRC_ProcessByte (&crc, b); 428 429 // sequence 430 b = p->sock->sendSequence; 431 TTY_WriteByte(p->tty, b); 432 if (b == ESCAPE_COMMAND) 433 TTY_WriteByte(p->tty, b); 434 CRC_ProcessByte (&crc, b); 435 436 // data length 437 b = message->cursize >> 8; 438 TTY_WriteByte(p->tty, b); 439 if (b == ESCAPE_COMMAND) 440 TTY_WriteByte(p->tty, b); 441 CRC_ProcessByte (&crc, b); 442 b = message->cursize & 0xff; 443 TTY_WriteByte(p->tty, b); 444 if (b == ESCAPE_COMMAND) 445 TTY_WriteByte(p->tty, b); 446 CRC_ProcessByte (&crc, b); 447 448 // data 449 for (n = 0; n < message->cursize; n++) 450 { 451 b = message->data[n]; 452 TTY_WriteByte(p->tty, b); 453 if (b == ESCAPE_COMMAND) 454 TTY_WriteByte(p->tty, b); 455 CRC_ProcessByte (&crc, b); 456 } 457 458 // checksum 459 b = CRC_Value (crc) >> 8; 460 TTY_WriteByte(p->tty, b); 461 if (b == ESCAPE_COMMAND) 462 TTY_WriteByte(p->tty, b); 463 b = CRC_Value (crc) & 0xff; 464 TTY_WriteByte(p->tty, b); 465 if (b == ESCAPE_COMMAND) 466 TTY_WriteByte(p->tty, b); 467 468 // end of message 469 TTY_WriteByte(p->tty, ESCAPE_COMMAND); 470 TTY_WriteByte(p->tty, ESCAPE_EOM); 471 472 TTY_Flush(p->tty); 473 474 // mark sock as busy and save the message for possible retransmit 475 sock->canSend = false; 476 Q_memcpy(sock->sendMessage, message->data, message->cursize); 477 sock->sendMessageLength = message->cursize; 478 sock->lastSendTime = net_time; 479 480 return 1; 481 } 482 483 484 static void ReSendMessage (qsocket_t *sock) 485 { 486 sizebuf_t temp; 487 488 Con_DPrintf("Serial: re-sending reliable\n"); 489 temp.data = sock->sendMessage; 490 temp.maxsize = sock->sendMessageLength; 491 temp.cursize = sock->sendMessageLength; 492 Serial_SendMessage (sock, &temp); 493 } 494 495 496 int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message) 497 { 498 SerialLine *p; 499 int n; 500 unsigned short crc; 501 byte b; 502 503 p = (SerialLine *)sock->driverdata; 504 505 if (!TTY_OutputQueueIsEmpty(p->tty)) 506 { 507 TTY_Flush(p->tty); 508 return 1; 509 } 510 511 CRC_Init (&crc); 512 513 // message type 514 b = MTYPE_UNRELIABLE; 515 if (p->client) 516 b |= MTYPE_CLIENT; 517 TTY_WriteByte(p->tty, b); 518 CRC_ProcessByte (&crc, b); 519 520 // sequence 521 b = p->sock->unreliableSendSequence; 522 p->sock->unreliableSendSequence = (b + 1) & 0xff; 523 TTY_WriteByte(p->tty, b); 524 if (b == ESCAPE_COMMAND) 525 TTY_WriteByte(p->tty, b); 526 CRC_ProcessByte (&crc, b); 527 528 // data length 529 b = message->cursize >> 8; 530 TTY_WriteByte(p->tty, b); 531 if (b == ESCAPE_COMMAND) 532 TTY_WriteByte(p->tty, b); 533 CRC_ProcessByte (&crc, b); 534 b = message->cursize & 0xff; 535 TTY_WriteByte(p->tty, b); 536 if (b == ESCAPE_COMMAND) 537 TTY_WriteByte(p->tty, b); 538 CRC_ProcessByte (&crc, b); 539 540 // data 541 for (n = 0; n < message->cursize; n++) 542 { 543 b = message->data[n]; 544 TTY_WriteByte(p->tty, b); 545 if (b == ESCAPE_COMMAND) 546 TTY_WriteByte(p->tty, b); 547 CRC_ProcessByte (&crc, b); 548 } 549 550 // checksum 551 b = CRC_Value (crc) >> 8; 552 TTY_WriteByte(p->tty, b); 553 if (b == ESCAPE_COMMAND) 554 TTY_WriteByte(p->tty, b); 555 b = CRC_Value (crc) & 0xff; 556 TTY_WriteByte(p->tty, b); 557 if (b == ESCAPE_COMMAND) 558 TTY_WriteByte(p->tty, b); 559 560 // end of message 561 TTY_WriteByte(p->tty, ESCAPE_COMMAND); 562 TTY_WriteByte(p->tty, ESCAPE_EOM); 563 564 TTY_Flush(p->tty); 565 566 return 1; 567 } 568 569 570 static void Serial_SendACK (SerialLine *p, byte sequence) 571 { 572 unsigned short crc; 573 byte b; 574 575 CRC_Init (&crc); 576 577 // message type 578 b = MTYPE_ACK; 579 if (p->client) 580 b |= MTYPE_CLIENT; 581 TTY_WriteByte(p->tty, b); 582 CRC_ProcessByte (&crc, b); 583 584 // sequence 585 b = sequence; 586 TTY_WriteByte(p->tty, b); 587 if (b == ESCAPE_COMMAND) 588 TTY_WriteByte(p->tty, b); 589 CRC_ProcessByte (&crc, b); 590 591 // checksum 592 b = CRC_Value (crc) >> 8; 593 TTY_WriteByte(p->tty, b); 594 if (b == ESCAPE_COMMAND) 595 TTY_WriteByte(p->tty, b); 596 b = CRC_Value (crc) & 0xff; 597 TTY_WriteByte(p->tty, b); 598 if (b == ESCAPE_COMMAND) 599 TTY_WriteByte(p->tty, b); 600 601 // end of message 602 TTY_WriteByte(p->tty, ESCAPE_COMMAND); 603 TTY_WriteByte(p->tty, ESCAPE_EOM); 604 605 TTY_Flush(p->tty); 606 } 607 608 609 static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message) 610 { 611 unsigned short crc; 612 int n; 613 byte b; 614 615 CRC_Init (&crc); 616 617 // message type 618 b = MTYPE_CONTROL; 619 if (p->client) 620 b |= MTYPE_CLIENT; 621 TTY_WriteByte(p->tty, b); 622 CRC_ProcessByte (&crc, b); 623 624 // data length 625 b = message->cursize >> 8; 626 TTY_WriteByte(p->tty, b); 627 if (b == ESCAPE_COMMAND) 628 TTY_WriteByte(p->tty, b); 629 CRC_ProcessByte (&crc, b); 630 b = message->cursize & 0xff; 631 TTY_WriteByte(p->tty, b); 632 if (b == ESCAPE_COMMAND) 633 TTY_WriteByte(p->tty, b); 634 CRC_ProcessByte (&crc, b); 635 636 // data 637 for (n = 0; n < message->cursize; n++) 638 { 639 b = message->data[n]; 640 TTY_WriteByte(p->tty, b); 641 if (b == ESCAPE_COMMAND) 642 TTY_WriteByte(p->tty, b); 643 CRC_ProcessByte (&crc, b); 644 } 645 646 // checksum 647 b = CRC_Value (crc) >> 8; 648 TTY_WriteByte(p->tty, b); 649 if (b == ESCAPE_COMMAND) 650 TTY_WriteByte(p->tty, b); 651 b = CRC_Value (crc) & 0xff; 652 TTY_WriteByte(p->tty, b); 653 if (b == ESCAPE_COMMAND) 654 TTY_WriteByte(p->tty, b); 655 656 // end of message 657 TTY_WriteByte(p->tty, ESCAPE_COMMAND); 658 TTY_WriteByte(p->tty, ESCAPE_EOM); 659 660 TTY_Flush(p->tty); 661 } 662 663 664 static int _Serial_GetMessage (SerialLine *p) 665 { 666 byte ret; 667 short length; 668 669 if (ProcessInQueue(p)) 670 return -1; 671 672 if (p->sock->receiveMessageLength == 0) 673 return 0; 674 675 ret = p->sock->receiveMessage[0]; 676 length = *(short *)&p->sock->receiveMessage[1]; 677 if (ret == MTYPE_CONTROL) 678 ret = 1; 679 680 SZ_Clear (&net_message); 681 SZ_Write (&net_message, &p->sock->receiveMessage[3], length); 682 683 length += 3; 684 p->sock->receiveMessageLength -= length; 685 686 if (p->sock->receiveMessageLength + p->lengthFound) 687 Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound); 688 689 return ret; 690 } 691 692 int Serial_GetMessage (qsocket_t *sock) 693 { 694 SerialLine *p; 695 int ret; 696 697 p = (SerialLine *)sock->driverdata; 698 699 ret = _Serial_GetMessage (p); 700 701 if (ret == 1) 702 messagesReceived++; 703 704 if (!sock->canSend) 705 if ((net_time - sock->lastSendTime) > 1.0) 706 { 707 ReSendMessage (sock); 708 sock->lastSendTime = net_time; 709 } 710 711 return ret; 712 } 713 714 715 void Serial_Close (qsocket_t *sock) 716 { 717 SerialLine *p = (SerialLine *)sock->driverdata; 718 TTY_Close(p->tty); 719 ResetSerialLineProtocol (p); 720 } 721 722 723 char *com_types[] = {"direct", "modem"}; 724 unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600}; 725 726 void Serial_SearchForHosts (qboolean xmit) 727 { 728 int n; 729 SerialLine *p; 730 731 if (sv.active) 732 return; 733 734 if (hostCacheCount == HOSTCACHESIZE) 735 return; 736 737 // see if we've already answered 738 for (n = 0; n < hostCacheCount; n++) 739 if (Q_strcmp (hostcache[n].cname, "#") == 0) 740 return; 741 742 for (n = 0; n < NUM_COM_PORTS; n++) 743 if (TTY_IsEnabled(n)) 744 break; 745 if (n == NUM_COM_PORTS) 746 return; 747 p = &serialLine[n]; 748 749 if (TTY_IsModem(p->tty)) 750 return; 751 752 sprintf(hostcache[hostCacheCount].name, "COM%u", n+1); 753 Q_strcpy(hostcache[hostCacheCount].map, ""); 754 hostcache[hostCacheCount].users = 0; 755 hostcache[hostCacheCount].maxusers = 0; 756 hostcache[hostCacheCount].driver = net_driverlevel; 757 Q_strcpy(hostcache[hostCacheCount].cname, "#"); 758 hostCacheCount++; 759 760 return; 761 } 762 763 764 static qsocket_t *_Serial_Connect (char *host, SerialLine *p) 765 { 766 int ret; 767 double start_time; 768 double last_time; 769 770 p->client = true; 771 if (TTY_Connect(p->tty, host)) 772 return NULL; 773 774 p->sock = NET_NewQSocket (); 775 p->sock->driver = myDriverLevel; 776 if (p->sock == NULL) 777 { 778 Con_Printf("No sockets available\n"); 779 return NULL; 780 } 781 p->sock->driverdata = p; 782 783 // send the connection request 784 start_time = SetNetTime(); 785 last_time = 0.0; 786 787 SZ_Clear(&net_message); 788 MSG_WriteByte(&net_message, CCREQ_CONNECT); 789 MSG_WriteString(&net_message, "QUAKE"); 790 do 791 { 792 SetNetTime(); 793 if ((net_time - last_time) >= 1.0) 794 { 795 Serial_SendControlMessage (p, &net_message); 796 last_time = net_time; 797 Con_Printf("trying...\n"); SCR_UpdateScreen (); 798 } 799 ret = _Serial_GetMessage (p); 800 } 801 while (ret == 0 && (net_time - start_time) < 5.0); 802 803 if (ret == 0) 804 { 805 Con_Printf("Unable to connect, no response\n"); 806 goto ErrorReturn; 807 } 808 809 if (ret == -1) 810 { 811 Con_Printf("Connection request error\n"); 812 goto ErrorReturn; 813 } 814 815 MSG_BeginReading (); 816 ret = MSG_ReadByte(); 817 if (ret == CCREP_REJECT) 818 { 819 Con_Printf(MSG_ReadString()); 820 goto ErrorReturn; 821 } 822 if (ret != CCREP_ACCEPT) 823 { 824 Con_Printf("Unknown connection response\n"); 825 goto ErrorReturn; 826 } 827 828 p->connected = true; 829 p->sock->lastMessageTime = net_time; 830 831 Con_Printf ("Connection accepted\n"); 832 833 return p->sock; 834 835 ErrorReturn: 836 TTY_Disconnect(p->tty); 837 return NULL; 838 } 839 840 qsocket_t *Serial_Connect (char *host) 841 { 842 int n; 843 qsocket_t *ret = NULL; 844 845 // see if this looks like a phone number 846 if (*host == '#') 847 host++; 848 for (n = 0; n < Q_strlen(host); n++) 849 if (host[n] == '.' || host[n] == ':') 850 return NULL; 851 852 for (n = 0; n < NUM_COM_PORTS; n++) 853 if (TTY_IsEnabled(n) && !serialLine[n].connected) 854 if ((ret = _Serial_Connect (host, &serialLine[n]))) 855 break; 856 return ret; 857 } 858 859 860 static qsocket_t *_Serial_CheckNewConnections (SerialLine *p) 861 { 862 int command; 863 864 p->client = false; 865 if (!TTY_CheckForConnection(p->tty)) 866 return NULL; 867 868 if (TTY_IsModem(p->tty)) 869 { 870 if (!p->connecting) 871 { 872 p->connecting = true; 873 p->connect_time = net_time; 874 } 875 else if ((net_time - p->connect_time) > 15.0) 876 { 877 p->connecting = false; 878 TTY_Disconnect(p->tty); 879 return NULL; 880 } 881 } 882 883 p->sock = NET_NewQSocket (); 884 p->sock->driver = myDriverLevel; 885 if (p->sock == NULL) 886 { 887 Con_Printf("No sockets available\n"); 888 return NULL; 889 } 890 p->sock->driverdata = p; 891 892 SZ_Clear(&net_message); 893 if (_Serial_GetMessage(p) != 1) 894 { 895 NET_FreeQSocket(p->sock); 896 return NULL; 897 } 898 899 MSG_BeginReading (); 900 command = MSG_ReadByte(); 901 902 if (command == CCREQ_SERVER_INFO) 903 { 904 if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) 905 return NULL; 906 907 if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION) 908 return NULL; 909 910 SZ_Clear(&net_message); 911 MSG_WriteByte(&net_message, CCREP_SERVER_INFO); 912 MSG_WriteString(&net_message, hostname.string); 913 MSG_WriteString(&net_message, sv.name); 914 MSG_WriteByte(&net_message, net_activeconnections); 915 MSG_WriteByte(&net_message, svs.maxclients); 916 Serial_SendControlMessage (p, &net_message); 917 SZ_Clear(&net_message); 918 return NULL; 919 } 920 921 if (command != CCREQ_CONNECT) 922 return NULL; 923 924 if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) 925 return NULL; 926 927 // send him back the info about the server connection he has been allocated 928 SZ_Clear(&net_message); 929 MSG_WriteByte(&net_message, CCREP_ACCEPT); 930 Serial_SendControlMessage (p, &net_message); 931 SZ_Clear(&net_message); 932 933 p->connected = true; 934 p->connecting = false; 935 p->sock->lastMessageTime = net_time; 936 sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1)); 937 938 return p->sock; 939 } 940 941 qsocket_t *Serial_CheckNewConnections (void) 942 { 943 int n; 944 qsocket_t *ret = NULL; 945 946 for (n = 0; n < NUM_COM_PORTS; n++) 947 if (TTY_IsEnabled(n) && !serialLine[n].connected) 948 if ((ret = _Serial_CheckNewConnections (&serialLine[n]))) 949 break; 950 return ret; 951 } 952