root/src/dps8/fnptelnet.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. evHandler
  2. ltnConnect
  3. ltnConnect3270
  4. ltnEOR
  5. ltnDialout
  6. fnpTelnetInit
  7. fnp3270Init

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 24f735f0-f62f-11ec-b8af-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2016 Charles Anthony
   9  * Copyright (c) 2021-2024 The DPS8M Development Team
  10  *
  11  * This software is made available under the terms of the ICU License.
  12  * See the LICENSE.md file at the top-level directory of this distribution.
  13  *
  14  * ---------------------------------------------------------------------------
  15  */
  16 
  17 #include <stdio.h>
  18 #include <signal.h>
  19 
  20 #include "dps8.h"
  21 #include "dps8_sys.h"
  22 #include "dps8_iom.h"
  23 #include "dps8_cable.h"
  24 #include "dps8_cpu.h"
  25 #include "dps8_faults.h"
  26 #include "dps8_scu.h"
  27 #include "dps8_fnp2.h"
  28 #include "dps8_utils.h"
  29 #include "fnpuv.h"
  30 #include "fnptelnet.h"
  31 
  32 static const telnet_telopt_t my_telopts[] = {
  33     { TELNET_TELOPT_SGA,       TELNET_WILL, TELNET_DO   },
  34     { TELNET_TELOPT_ECHO,      TELNET_WILL, TELNET_DONT },
  35   //{ TELNET_TELOPT_TTYPE,     TELNET_WONT, TELNET_DONT },
  36     { TELNET_TELOPT_BINARY,    TELNET_WILL, TELNET_DO   },
  37   //{ TELNET_TELOPT_NAWS,      TELNET_WONT, TELNET_DONT },
  38     { -1, 0, 0 }
  39   };
  40 
  41 static const telnet_telopt_t my_3270telopts[] = {
  42     { TELNET_TELOPT_TTYPE,     TELNET_WILL, TELNET_DO },
  43     { TELNET_TELOPT_BINARY,    TELNET_WILL, TELNET_DO },
  44     { TELNET_TELOPT_EOR,       TELNET_WILL, TELNET_DO },
  45     { -1, 0, 0 }
  46   };
  47 
  48 static void evHandler (UNUSED telnet_t *telnet, telnet_event_t *event, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  49   {
  50     uv_tcp_t * client = (uv_tcp_t *) user_data;
  51     switch (event->type)
  52       {
  53         case TELNET_EV_DATA:
  54           {
  55             if (! client || ! client->data)
  56               {
  57                 sim_warn ("evHandler TELNET_EV_DATA bad client data\r\n");
  58                 return;
  59               }
  60             uvClientData * p = (uvClientData *) client->data;
  61             (* p->read_cb) (client, (ssize_t) event->data.size, (unsigned char *)event->data.buffer);
  62           }
  63           break;
  64 
  65         case TELNET_EV_SEND:
  66           {
  67             //sim_printf ("evHandler: send %zu <%s>\n", event->data.size, event->data.buffer);
  68             //fnpuv_start_write_actual (client, (char *) event->data.buffer, (ssize_t) event->data.size);
  69             if (! client || ! client->data)
  70               {
  71                 sim_warn ("evHandler TELNET_EV_SEND bad client data\r\n");
  72                 return;
  73               }
  74             uvClientData * p = client->data;
  75             (* p->write_actual_cb) (client, (unsigned char *) event->data.buffer, (ssize_t) event->data.size);
  76           }
  77           break;
  78 
  79         case TELNET_EV_DO:
  80           {
  81             if (event->neg.telopt == TELNET_TELOPT_BINARY)
  82               {
  83                 // DO Binary
  84               }
  85             else if (event->neg.telopt == TELNET_TELOPT_SGA)
  86               {
  87                 // DO Suppress Go Ahead
  88               }
  89             else if (event->neg.telopt == TELNET_TELOPT_ECHO)
  90               {
  91                 // DO Suppress Echo
  92               }
  93             else if (event->neg.telopt == TELNET_TELOPT_EOR)
  94               {
  95                 //sim_printf ("EOR rcvd\n");
  96                 //fnpuv_recv_eor (client);
  97                 // DO EOR
  98               }
  99             else
 100               {
 101                 sim_printf ("evHandler DO %d\n", event->neg.telopt);
 102               }
 103           }
 104           break;
 105 
 106         case TELNET_EV_DONT:
 107           {
 108             sim_printf ("evHandler DONT %d\n", event->neg.telopt);
 109           }
 110           break;
 111 
 112         case TELNET_EV_WILL:
 113           {
 114             if (event->neg.telopt == TELNET_TELOPT_BINARY)
 115               {
 116                 // WILL BINARY
 117               }
 118             else if (event->neg.telopt == TELNET_TELOPT_TTYPE)
 119               {
 120                 // WILL TTYPE
 121               }
 122             else if (event->neg.telopt == TELNET_TELOPT_EOR)
 123               {
 124                 // WILL EOR
 125               }
 126             else
 127               {
 128                 if (event->neg.telopt != 3)
 129                   sim_printf ("evHandler WILL %d\n", event->neg.telopt);
 130               }
 131           }
 132           break;
 133 
 134         case TELNET_EV_WONT:
 135           {
 136             sim_printf ("evHandler WONT %d\n", event->neg.telopt);
 137           }
 138           break;
 139 
 140         case TELNET_EV_ERROR:
 141           {
 142             sim_warn ("libtelnet evHandler error <%s>\n", event->error.msg);
 143           }
 144           break;
 145 
 146         case TELNET_EV_IAC:
 147           {
 148             if (event->iac.cmd == TELNET_BREAK ||
 149                 event->iac.cmd == TELNET_IP)
 150               {
 151                 if (! client || ! client->data)
 152                   {
 153                     sim_warn ("evHandler TELNET_EV_IAC bad client data\r\n");
 154                     return;
 155                   }
 156                 uvClientData * p = (uvClientData *) client->data;
 157                 if (p -> assoc)
 158                   {
 159                     fnpuv_associated_brk (client);
 160                   }
 161                 else
 162                   sim_warn ("libtelnet dropping unassociated BRK\n");
 163               }
 164             else if (event->iac.cmd == TELNET_EOR)
 165               {
 166                 fnpuv_recv_eor (client);
 167               }
 168             else
 169               if ((!sim_quiet) || (event->iac.cmd != 241))
 170                 sim_warn ("libtelnet unhandled IAC event %d\n", event->iac.cmd);
 171           }
 172           break;
 173 
 174         case TELNET_EV_TTYPE:
 175           {
 176             if (! client || ! client->data)
 177               {
 178                 sim_warn ("evHandler TELNET_EV_IAC bad client data\r\n");
 179                 return;
 180               }
 181             uvClientData * p = (uvClientData *) client->data;
 182             p->ttype = strdup (event->ttype.name);
 183             if (!p->ttype)
 184               {
 185                 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 186                                __func__, __FILE__, __LINE__);
 187 #if defined(USE_BACKTRACE)
 188 # if defined(SIGUSR2)
 189                 (void)raise(SIGUSR2);
 190                 /*NOTREACHED*/ /* unreachable */
 191 # endif /* if defined(SIGUSR2) */
 192 #endif /* if defined(USE_BACKTRACE) */
 193                 abort();
 194               }
 195           }
 196           break;
 197 
 198         case TELNET_EV_SUBNEGOTIATION:
 199           {
 200             /* no subnegotiation */
 201           }
 202           break;
 203 
 204         default:
 205           sim_printf ("evHandler: unhandled event %d\n", event->type);
 206           break;
 207       }
 208 
 209   }
 210 
 211 void * ltnConnect (uv_tcp_t * client)
     /* [previous][next][first][last][top][bottom][index][help] */
 212   {
 213     void * p = (void *) telnet_init (my_telopts, evHandler, 0, client);
 214     if (! p)
 215       {
 216         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 217                        __func__, __FILE__, __LINE__);
 218 #if defined(USE_BACKTRACE)
 219 # if defined(SIGUSR2)
 220         (void)raise(SIGUSR2);
 221         /*NOTREACHED*/ /* unreachable */
 222 # endif /* if defined(SIGUSR2) */
 223 #endif /* if defined(USE_BACKTRACE) */
 224         abort();
 225       }
 226     const telnet_telopt_t * q = my_telopts;
 227     while (q->telopt != -1)
 228       {
 229         telnet_negotiate (p, q->us, (unsigned char) q->telopt);
 230         q ++;
 231       }
 232     return p;
 233   }
 234 
 235 void * ltnConnect3270 (uv_tcp_t * client)
     /* [previous][next][first][last][top][bottom][index][help] */
 236   {
 237     void * p = (void *) telnet_init (my_3270telopts, evHandler, 0, client);
 238     if (! p)
 239       {
 240         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 241                        __func__, __FILE__, __LINE__);
 242 #if defined(USE_BACKTRACE)
 243 # if defined(SIGUSR2)
 244         (void)raise(SIGUSR2);
 245         /*NOTREACHED*/ /* unreachable */
 246 # endif /* if defined(SIGUSR2) */
 247 #endif /* if defined(USE_BACKTRACE) */
 248         abort();
 249       }
 250 
 251     // This behavior is copied from Hercules.
 252     telnet_negotiate (p, TELNET_DO, (unsigned char) TELNET_TELOPT_TTYPE);
 253     telnet_begin_sb  (p, TELNET_TELOPT_TTYPE);
 254     const char ttype [1] = { 1 };
 255     telnet_send (p, ttype, 1);
 256     telnet_finish_sb (p);
 257     telnet_negotiate (p, TELNET_WILL, (unsigned char) TELNET_TELOPT_BINARY);
 258     telnet_negotiate (p, TELNET_DO, (unsigned char) TELNET_TELOPT_BINARY);
 259     telnet_negotiate (p, TELNET_WILL, (unsigned char) TELNET_TELOPT_EOR);
 260     telnet_negotiate (p, TELNET_DO, (unsigned char) TELNET_TELOPT_EOR);
 261 
 262     return p;
 263   }
 264 
 265 void ltnEOR (telnet_t * tclient)
     /* [previous][next][first][last][top][bottom][index][help] */
 266   {
 267     telnet_iac (tclient, TELNET_EOR);
 268   }
 269 
 270 void ltnDialout (UNUSED telnet_t * tclient)
     /* [previous][next][first][last][top][bottom][index][help] */
 271   {
 272     // dialout telnet: We are a teletype. What settings should we be doing?
 273     //telnet_negotiate (tclient, TELNET_WILL, TELNET_TELOPT_SGA);
 274   }
 275 
 276 void fnpTelnetInit (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 277   {
 278 
 279 
 280 
 281 
 282 
 283 
 284 
 285 
 286 
 287 
 288 
 289 
 290 
 291   }
 292 
 293 void fnp3270Init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 294   {
 295   }

/* [previous][next][first][last][top][bottom][index][help] */