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-2025 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 
  52     if (! telnet || ! libtelnet_is_valid(telnet)) {
  53         if (! sim_quiet) {
  54             sim_warn ("evHandler telnet status invalid\r\n");
  55         }
  56         return;
  57     }
  58 
  59     switch (event->type)
  60       {
  61         case TELNET_EV_DATA:
  62           {
  63             if (! client || ! client->data)
  64               {
  65                 if (! sim_quiet) {
  66                     sim_warn ("evHandler TELNET_EV_DATA bad client data\r\n");
  67                 }
  68                 return;
  69               }
  70             uvClientData * p = (uvClientData *) client->data;
  71             (* p->read_cb) (client, (ssize_t) event->data.size, (unsigned char *)event->data.buffer);
  72           }
  73           break;
  74 
  75         case TELNET_EV_SEND:
  76           {
  77             //sim_printf ("evHandler: send %zu <%s>\r\n", event->data.size, event->data.buffer);
  78             //fnpuv_start_write_actual (client, (char *) event->data.buffer, (ssize_t) event->data.size);
  79             if (! client || ! client->data)
  80               {
  81                 if (! sim_quiet) {
  82                     sim_warn ("evHandler TELNET_EV_SEND bad client data\r\n");
  83                 }
  84                 return;
  85               }
  86             uvClientData * p = client->data;
  87             (* p->write_actual_cb) (client, (unsigned char *) event->data.buffer, (ssize_t) event->data.size);
  88           }
  89           break;
  90 
  91         case TELNET_EV_DO:
  92           {
  93             if (event->neg.telopt == TELNET_TELOPT_BINARY)
  94               {
  95                 // DO Binary
  96               }
  97             else if (event->neg.telopt == TELNET_TELOPT_SGA)
  98               {
  99                 // DO Suppress Go Ahead
 100               }
 101             else if (event->neg.telopt == TELNET_TELOPT_ECHO)
 102               {
 103                 // DO Suppress Echo
 104               }
 105             else if (event->neg.telopt == TELNET_TELOPT_EOR)
 106               {
 107                 //sim_printf ("EOR rcvd\r\n");
 108                 //fnpuv_recv_eor (client);
 109                 // DO EOR
 110               }
 111             else
 112               {
 113                 if (! sim_quiet) {
 114                     sim_printf ("evHandler DO %d\r\n", event->neg.telopt);
 115                 }
 116               }
 117           }
 118           break;
 119 
 120         case TELNET_EV_DONT:
 121           {
 122             if (! sim_quiet) {
 123                 sim_printf ("evHandler DONT %d\r\n", event->neg.telopt);
 124             }
 125           }
 126           break;
 127 
 128         case TELNET_EV_WILL:
 129           {
 130             if (event->neg.telopt == TELNET_TELOPT_BINARY)
 131               {
 132                 // WILL BINARY
 133               }
 134             else if (event->neg.telopt == TELNET_TELOPT_TTYPE)
 135               {
 136                 // WILL TTYPE
 137               }
 138             else if (event->neg.telopt == TELNET_TELOPT_EOR)
 139               {
 140                 // WILL EOR
 141               }
 142             else
 143               {
 144                 if (! sim_quiet) {
 145                     if (event->neg.telopt != 3)
 146                         sim_printf ("evHandler WILL %d\r\n", event->neg.telopt);
 147                 }
 148               }
 149           }
 150           break;
 151 
 152         case TELNET_EV_WONT:
 153           {
 154             if (! sim_quiet) {
 155                 sim_printf ("evHandler WONT %d\r\n", event->neg.telopt);
 156             }
 157           }
 158           break;
 159 
 160         case TELNET_EV_ERROR:
 161           {
 162             if (! sim_quiet) {
 163                 sim_warn ("libtelnet evHandler error <%s>\r\n", event->error.msg);
 164             }
 165           }
 166           break;
 167 
 168         case TELNET_EV_IAC:
 169           {
 170             if (event->iac.cmd == TELNET_BREAK ||
 171                 event->iac.cmd == TELNET_IP)
 172               {
 173                 if (! client || ! client->data)
 174                   {
 175                     if (! sim_quiet) {
 176                         sim_warn ("evHandler TELNET_EV_IAC bad client data\r\n");
 177                     }
 178                     return;
 179                   }
 180                 uvClientData * p = (uvClientData *) client->data;
 181                 if (p -> assoc)
 182                   {
 183                     fnpuv_associated_brk (client);
 184                   }
 185                 else
 186                   if (! sim_quiet) {
 187                     sim_warn ("libtelnet dropping unassociated BRK\r\n");
 188                   }
 189               }
 190             else if (event->iac.cmd == TELNET_EOR)
 191               {
 192                 fnpuv_recv_eor (client);
 193               }
 194             else
 195               if (! sim_quiet) {
 196                 if (event->iac.cmd != 241) {
 197                     sim_warn ("libtelnet unhandled IAC event %d\r\n", event->iac.cmd);
 198                 }
 199               }
 200           }
 201           break;
 202 
 203         case TELNET_EV_TTYPE:
 204           {
 205             if (! client || ! client->data)
 206               {
 207                 if (! sim_quiet) {
 208                     sim_warn ("evHandler TELNET_EV_IAC bad client data\r\n");
 209                 }
 210                 return;
 211               }
 212             uvClientData * p = (uvClientData *) client->data;
 213             p->ttype = strdup (event->ttype.name);
 214             if (!p->ttype)
 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           }
 227           break;
 228 
 229         case TELNET_EV_SUBNEGOTIATION:
 230           {
 231             /* no subnegotiation */
 232           }
 233           break;
 234 
 235         default:
 236           if (! sim_quiet) {
 237             sim_printf ("evHandler: unhandled event %d\r\n", event->type);
 238           }
 239           break;
 240       }
 241 
 242   }
 243 
 244 void * ltnConnect (uv_tcp_t * client)
     /* [previous][next][first][last][top][bottom][index][help] */
 245   {
 246     void * p = (void *) telnet_init (my_telopts, evHandler, 0, client);
 247     if (! p)
 248       {
 249         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 250                        __func__, __FILE__, __LINE__);
 251 #if defined(USE_BACKTRACE)
 252 # if defined(SIGUSR2)
 253         (void)raise(SIGUSR2);
 254         /*NOTREACHED*/ /* unreachable */
 255 # endif /* if defined(SIGUSR2) */
 256 #endif /* if defined(USE_BACKTRACE) */
 257         abort();
 258       }
 259     const telnet_telopt_t * q = my_telopts;
 260     while (q->telopt != -1)
 261       {
 262         telnet_negotiate (p, q->us, (unsigned char) q->telopt);
 263         q ++;
 264       }
 265     return p;
 266   }
 267 
 268 void * ltnConnect3270 (uv_tcp_t * client)
     /* [previous][next][first][last][top][bottom][index][help] */
 269   {
 270     void * p = (void *) telnet_init (my_3270telopts, evHandler, 0, client);
 271     if (! p)
 272       {
 273         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 274                        __func__, __FILE__, __LINE__);
 275 #if defined(USE_BACKTRACE)
 276 # if defined(SIGUSR2)
 277         (void)raise(SIGUSR2);
 278         /*NOTREACHED*/ /* unreachable */
 279 # endif /* if defined(SIGUSR2) */
 280 #endif /* if defined(USE_BACKTRACE) */
 281         abort();
 282       }
 283 
 284     // This behavior is copied from Hercules.
 285     telnet_negotiate (p, TELNET_DO, (unsigned char) TELNET_TELOPT_TTYPE);
 286     telnet_begin_sb  (p, TELNET_TELOPT_TTYPE);
 287     const char ttype [1] = { 1 };
 288     telnet_send (p, ttype, 1);
 289     telnet_finish_sb (p);
 290     telnet_negotiate (p, TELNET_WILL, (unsigned char) TELNET_TELOPT_BINARY);
 291     telnet_negotiate (p, TELNET_DO, (unsigned char) TELNET_TELOPT_BINARY);
 292     telnet_negotiate (p, TELNET_WILL, (unsigned char) TELNET_TELOPT_EOR);
 293     telnet_negotiate (p, TELNET_DO, (unsigned char) TELNET_TELOPT_EOR);
 294 
 295     return p;
 296   }
 297 
 298 void ltnEOR (telnet_t * tclient)
     /* [previous][next][first][last][top][bottom][index][help] */
 299   {
 300     telnet_iac (tclient, TELNET_EOR);
 301   }
 302 
 303 void ltnDialout (UNUSED telnet_t * tclient)
     /* [previous][next][first][last][top][bottom][index][help] */
 304   {
 305     // dialout telnet: We are a teletype. What settings should we be doing?
 306     //telnet_negotiate (tclient, TELNET_WILL, TELNET_TELOPT_SGA);
 307   }
 308 
 309 void fnpTelnetInit (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 310   {
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 
 319 
 320 
 321 
 322 
 323 
 324   }
 325 
 326 void fnp3270Init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 327   {
 328   }

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