net_ser.c 20 KB

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