home *** CD-ROM | disk | FTP | other *** search
- /*
- PMICS -- PM interface for playing chess on internet chess server
- Copyright (C) 1994 Kevin Nomura
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Author can be reached at email: chow@netcom.com
- */
- #ifdef TCP_SESSION
- #include <strstrea.h>
- #include "pmics.hh"
- #include "session.hh"
- #include "wcomm.hh"
- #define INCL_DOSPROCESS
- #define INCL_DOSFILEMGR
- #define INCL_DOSDEVIOCTL
- #define INCL_DOSDEVICES
- #define INCL_DOSDATETIME
- #define INCL_DOSQUEUES
- #define INCL_DOSEXCEPTIONS
- #include <os2.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <istring.hpp>
- #include <iexcbase.hpp>
-
- #define ICS_PORT_DEFAULT 5000
- #define ICS_HOST_DEFAULT "chess.lm.com"
- #define SE 240
- #define SB 250
- #define WILL 251
- #define WONT 252
- #define DO 253
- #define DONT 254
- #define IAC 255
-
- #define ECHO 1
- #define SUPPRESS_GO_AHEAD 3
- #define TTYPE 24
- #define NAWS 31
- #define LINEMODE 34
- #define ENV_VARS 36
-
- #define CMDX(b1,b2) { char ch[4]; \
- ch[0]=IAC; ch[1]=b1; ch[2]=b2; aSession->write(ch,3); }
- #define CMD(b1,b2) { char ch[4]; \
- ch[0]=IAC; ch[1]=b1; ch[2]=b2; write(ch,3); }
-
- extern IString getStringOption(IString s, IString def);
- extern int getIntOption(IString s, int def);
-
- /**************************************************************************
- *
- * Global Variables
- *
- *************************************************************************/
- extern strstream commStream;
- extern ASession *aSession;
- static char theAppName[] = "pmics";
- static VOID _System TcpListen(ULONG sock);
-
- /**************************************************************************
- **************************************************************************
- *
- * Routines
- *
- **************************************************************************
- *************************************************************************/
-
- ATcpSession::ATcpSession()
- {
- EtherInit (); // defines sock
- listenThread = new IThread(&TcpListen, (ULONG)sock);
-
- CMD(WILL, NAWS);
- CMD(DO, ECHO);
- CMD(DO, SUPPRESS_GO_AHEAD);
- }
-
-
- /**************************************************************************
- *
- * EtherClose ( )
- *
- * Close the currently open ethernet port
- *
- *************************************************************************/
-
- ATcpSession::~ATcpSession ( )
- {
- soclose(sock);
- sock = 0;
- }
-
- /**************************************************************************
- *
- * EtherInit ( )
- *
- *************************************************************************/
-
- void ATcpSession::EtherInit ()
- {
- struct sockaddr_in serveri;
- IString tcphost;
- int tcpport;
- unsigned long icsaddr;
- struct in_addr inaddr;
-
- tcphost = getStringOption("tcphost", ICS_HOST_DEFAULT);
- tcpport = getIntOption("tcpport", ICS_PORT_DEFAULT);
-
- if (tcphost.subString(1,1).isDigits()) {
- icsaddr = inet_addr(tcphost);
- }
- else {
- struct hostent *hp;
- if ((hp = gethostbyname(tcphost)) == NULL) {
- throw IException(IString("Hostname cannot be resolved: ") + tcphost);
- }
- icsaddr = (hp->h_addr[3]<<24) |
- (hp->h_addr[2]<<16) |
- (hp->h_addr[1]<<8) |
- (hp->h_addr[0]);
- }
- inaddr.s_addr = icsaddr;
- ITRACE_DEVELOP("tcphost="+tcphost+
- " icsaddr="+IString(inet_ntoa(inaddr))+
- " tcpport="+IString(tcpport));
-
- bzero((char *)&serveri, sizeof (serveri));
- serveri.sin_family = AF_INET;
- serveri.sin_port = htons(tcpport);
- serveri.sin_addr.s_addr = icsaddr;
-
- sock = socket ( AF_INET, SOCK_STREAM, 0 );
- if ( sock < 0 ) {
- perror("");
- throw IException(IString(theAppName) + "unable to create socket.");
- }
-
- if (connect(sock,(struct sockaddr *)&serveri, sizeof(serveri)) < 0) {
- perror("");
- throw IException(IString(theAppName) + "unable to open connection.");
- }
- }
-
-
-
- /**************************************************************************
- *
- * write ( value )
- *
- * Send *value* out the specified serial port
- *
- *************************************************************************/
-
- int ATcpSession::write (char *data)
- {
- return write(data, strlen(data));
- }
-
-
- int ATcpSession::write (char *data, int len)
- {
- int status;
-
- status = send ( sock , data, len, 0 );
- return status;
- }
-
-
- /**************************************************************************
- *
- * EtherInt ()
- *
- * 4.2 interrupt routine
- *
- *************************************************************************/
-
- typedef enum STATE_ {
- S_START = 0,
- S_IAC,
- S_IAC_DO,
- S_IAC_DONT,
- S_IAC_WILL,
- S_IAC_WONT,
- S_IAC_SB,
- S_IAC_SB_TTYPE,
- S_IAC_SB_TTYPE_SEND,
- S_IAC_SB_TTYPE_SEND_IAC
- } STATE;
-
- /*****************************************************************************/
- /* thread does blocking reads against COM: and send data via window */
- /* messages to the parent window as data arrives */
- /*****************************************************************************/
- static VOID _System TcpListen(ULONG sock_)
- {
- int sock = sock_;
- int bytesRead;
- char ch[32], *s;
- int tok;
- static STATE state = S_START;
- static char buf[2049], cooked[2049], *putp;
-
- IFUNCTRACE_DEVELOP();
- ITRACE_DEVELOP(IString("listening to com port"));
- if (! IThread::current().isPMInitialized())
- IThread::current().initializePM();
-
- while (1) {
- bytesRead = recv(sock, buf, 2048, 0);
- if (bytesRead <= 0) continue;
- buf[bytesRead] = 0; // for debug print
-
- ITRACE_DEVELOP(IString(bytesRead) + " bytes received from socket");
-
- putp = cooked;
- for (int i=0; i < bytesRead; i++) {
- tok = (int) buf[i];
- // ITRACE_DEVELOP(IString(tok));
-
- switch(state) {
- case S_START:
- if (tok == IAC) state = S_IAC;
- else if (tok) *putp++ = tok;
- break;
-
- case S_IAC: // IAC seen
- switch(tok) {
- case DO: state = S_IAC_DO; break;
- case DONT: state = S_IAC_DONT; break;
- case WILL: state = S_IAC_WILL; break;
- case WONT: state = S_IAC_WONT; break;
- case SB: state = S_IAC_SB; break;
-
- default: state=S_START;
- }
- break;
-
- case S_IAC_DO:
- if (tok == TTYPE) {
- ITRACE_DEVELOP("RCVD do TTYPE");
- CMDX(WILL, TTYPE);
- ITRACE_DEVELOP("SEND will TTYPE");
- }
- else if (tok == NAWS) {
- ITRACE_DEVELOP("RCVD do NAWS");
- s = ch;
- *s++ = IAC;
- *s++ = SB;
- *s++ = NAWS;
- *s++ = 0;
- *s++ = 80;
- *s++ = 0;
- *s++ = 24;
- *s++ = IAC;
- *s++ = SE;
- aSession->write(ch, 9);
- ITRACE_DEVELOP("SEND suboption NAWS 80x24");
- }
- state = S_START;
- break;
-
- case S_IAC_SB:
- if (tok == TTYPE) state = S_IAC_SB_TTYPE;
- else state = S_START;
- break;
-
- case S_IAC_SB_TTYPE:
- if (tok == 1) state = S_IAC_SB_TTYPE_SEND;
- else state = S_START;
- break;
-
- case S_IAC_SB_TTYPE_SEND:
- if (tok == IAC) state = S_IAC_SB_TTYPE_SEND_IAC;
- else state = S_START;
- break;
-
- case S_IAC_SB_TTYPE_SEND_IAC:
- if (tok == SE) {
- ITRACE_DEVELOP("RCVD suboption TELOPT_TTYPE SEND");
- // send terminal type
- s = ch;
- *s++ = IAC;
- *s++ = SB;
- *s++ = TTYPE;
- *s++ = 0;
- *s++ = 'v';
- *s++ = 't';
- *s++ = '1';
- *s++ = '0';
- *s++ = '0';
- *s++ = IAC;
- *s++ = SE;
- aSession->write(ch, 11);
- ITRACE_DEVELOP("SEND suboption TELOPT_TTYPE xterm");
- }
- state = S_START;
- break;
-
- default:
- state = S_START;
- break;
- }
- }
-
- if (putp - cooked == 0)
- continue;
- commStream.clear();
- commStream.write(cooked, putp - cooked);
-
- while(1) {
- try {
- hComm.postEvent(MSG_COM_IN);
- break;
- }
- catch (IInvalidParameter) {
- ITRACE_DEVELOP("ComListen: exception caught, sleeping 250");
- // IThread::current().sleep(250);
- }
- }
-
- if (bytesRead < 16) // avoid flooding queue
- // IThread::current().sleep(100);
- ;
- }
- }
- #endif
-