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

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