File size: 1,872 Bytes
d4c5ec7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Small helpers around the mTCP TCP/IP library for DOS programs: stack start/stop, DNS, clock, ports.
// Copyright (C) 2026. GPL-3.0-or-later (links against mTCP, GPL-3.0-or-later).
#ifndef DOSNET_H
#define DOSNET_H

#include <dos.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "types.h"
#include "trace.h"
#include "utils.h"
#include "packet.h"
#include "arp.h"
#include "udp.h"
#include "dns.h"
#include "tcp.h"
#include "tcpsockm.h"
#include "timer.h"

volatile uint8_t CtrlBreakDetected = 0;
void __interrupt __far ctrlBreakHandler( ) { CtrlBreakDetected = 1; }
void __interrupt __far ctrlCHandler( ) { /* Ctrl-C is a legal character: do nothing */ }

// "HH:MM:SS" from the DOS real-time clock (UTC in the emulator).
static void stamp( char *out ) {
  struct dostime_t t;
  _dos_gettime( &t );
  sprintf( out, "%02d:%02d:%02d", t.hour, t.minute, t.second );
}

// A local TCP port that differs between runs (derived from the clock).
static uint16_t pseudoPort( void ) {
  struct dostime_t t;
  _dos_gettime( &t );
  return (uint16_t)( 3000 + ( (uint16_t)t.second * 100 + t.hsecond ) % 20000 );
}

static void netShutdown( int rc ) {
  Utils::endStack( );
  exit( rc );
}

// Read MTCPCFG, hook the timer, start the stack (2 TCP sockets). Returns 0 on success.
static int netInit( void ) {
  if ( Utils::parseEnv( ) != 0 ) return -1;
  if ( Utils::initStack( 2, TCP_SOCKET_RING_SIZE, ctrlBreakHandler, ctrlCHandler ) ) return -1;
  return 0;
}

// Blocking DNS lookup. Returns 0 on success.
static int resolveHost( const char *name, IpAddr_t addr ) {
  int8_t rc = Dns::resolve( name, addr, 1 );
  if ( rc < 0 ) return -1;
  while ( !CtrlBreakDetected && Dns::isQueryPending( ) ) {
    Utils::processPackets( );
    Dns::drivePendingQuery( );
  }
  rc = Dns::resolve( name, addr, 0 );
  return ( rc == 0 ) ? 0 : -1;
}

#endif