go3270

package module
v0.0.0-...-21f273b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2023 License: MIT Imports: 8 Imported by: 3

README

Go 3270 Server Library

PkgGoDev

This library allows you to write Go servers for tn3270 clients by building 3270 data streams from fields and processing the client's response to receive the attention keys and field values entered by users.

The library is incomplete, likely buggy, and under heavy development: the interface is UNSTABLE until this notice is removed from this readme and version 1.0 is released.

Everything I know about 3270 data streams I learned from Tommy Sprinkle's tutorial. The tn3270 telnet negotiation is gleaned from RFC 1576: TN3270 Current Practices, RFC 1041: Telnet 3270 Regime Option, and RFC 854: Telnet Protocol Specification. The IANA maintains a useful reference of telnet option numbers.

Usage

See the example folders for a quick demonstration of using the library. The examples are very similar, but example1 uses the lower-level function ShowScreen(), and example2 uses a higher-level function HandleScreen().

Here's a video introducing the library as well.

Future Enhancements

I would like to add:

  • Extended field attribute support (e.g. color). Done
  • Utility functions for easily laying out forms.

Known Problems

  • The telnet negotiation does not check for any errors or for any responses from the client. We just assume it goes well and we're actually talking to a tn3270 client.

License

This library is licensed under the MIT license; see the file LICENSE for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Debug io.Writer

Enable go3270 library debugging by setting Debug to an io.Writer. Disable debugging by setting it to nil (the default value).

Functions

func AIDtoString

func AIDtoString(aid AID) string

AIDtoString returns a string representation of an AID key name.

func NegotiateTelnet

func NegotiateTelnet(conn net.Conn) error

NegotiateTelnet will naively (e.g. not checking client responses) negotiate the options necessary for tn3270 on a new telnet connection, conn.

func UnNegotiateTelnet

func UnNegotiateTelnet(conn net.Conn, timeout time.Duration) error

UnNegotiateTelnet will naively (e.g. not checking client responses) attempt to restore the telnet options state to what it was before NegotiateTelnet() was called.

Types

type AID

type AID byte

AID is an Action ID character.

const (
	AIDNone  AID = 0x60
	AIDEnter AID = 0x7D
	AIDPF1   AID = 0xF1
	AIDPF2   AID = 0xF2
	AIDPF3   AID = 0xF3
	AIDPF4   AID = 0xF4
	AIDPF5   AID = 0xF5
	AIDPF6   AID = 0xF6
	AIDPF7   AID = 0xF7
	AIDPF8   AID = 0xF8
	AIDPF9   AID = 0xF9
	AIDPF10  AID = 0x7A
	AIDPF11  AID = 0x7B
	AIDPF12  AID = 0x7C
	AIDPF13  AID = 0xC1
	AIDPF14  AID = 0xC2
	AIDPF15  AID = 0xC3
	AIDPF16  AID = 0xC4
	AIDPF17  AID = 0xC5
	AIDPF18  AID = 0xC6
	AIDPF19  AID = 0xC7
	AIDPF20  AID = 0xC8
	AIDPF21  AID = 0xC9
	AIDPF22  AID = 0x4A
	AIDPF23  AID = 0x4B
	AIDPF24  AID = 0x4C
	AIDPA1   AID = 0x6C
	AIDPA2   AID = 0x6E
	AIDPA3   AID = 0x6B
	AIDClear AID = 0x6D
)

type Color

type Color byte

Color is a 3270 extended field attribute color value

const (
	DefaultColor Color = 0
	Blue         Color = 0xf1
	Red          Color = 0xf2
	Pink         Color = 0xf3
	Green        Color = 0xf4
	Turquoise    Color = 0xf5
	Yellow       Color = 0xf6
	White        Color = 0xf7
)

The valid 3270 colors

type Field

type Field struct {
	// Row is the row, 0-based, that the field attribute character should
	// begin at. This library currently only supports 24 rows, so Row must
	// be 0-23.
	Row int

	// Col is the column, 0-based, that the field attribute character should
	// begin at. This library currently only supposed 80 columns, so Column
	// must be 0-79.
	Col int

	// Text is the content of the field to display.
	Content string

	// Write allows the user to edit the value of the field.
	Write bool

	// Autoskip causes protected (Write = false) fields to automatically be
	// skipped and the cursor should move to the next field upon encountering
	// this field. Autoskip is ignored on fields with Write = true.
	Autoskip bool

	// Intense indicates this field should be displayed with high intensity.
	Intense bool

	// Hidden indicates the field content should not be displayed (e.g. a
	// password input field).
	Hidden bool

	// NumericOnly indicates that only numbers may be entered into the field.
	// Very fiew 3270 clients support this, so you must always still validate
	// the input on the server side.
	NumericOnly bool

	// Color is the field color. The default value is the default color.
	Color Color

	// Highlighting is the highlight attribute for the field. The default value
	// is the default (i.e. no) highlighting.
	Highlighting Highlight

	// Name is the name of this field, which is used to get the user-entered
	// data. All writeable fields on a screen must have a unique name.
	Name string

	// KeepSpaces will prevent the strings.TrimSpace() function from being
	// called on the field value. Generally you want leading and trailing
	// spaces trimmed from fields in 3270 before processing, but if you are
	// building a whitespace-sensitive application, you can ask for the
	// original, un-trimmed value for a field by setting this to true.
	KeepSpaces bool
}

Field is a field on the 3270 screen.

type FieldRules

type FieldRules struct {
	// MustChange, when true, indicates that the value of the field MUST be
	// altered by the user -- if applied to a field with no starting value,
	// this makes the field a required field. If true on a field with a
	// starting value (either in the field's Content attribute, or with an
	// override in the initial values map), then the user must change
	// the value from the default.
	MustChange bool

	// ErrorText is the text displayed with the MustChange validation fails.
	// If ErrorText is the empty string, but MustValidation fails, an error
	// string will be constructed from the field name: "Please enter a valid
	// value for <fieldName>."
	ErrorText string

	// Validator is a function to validate the value the user input into the
	// field. It may be nil if no validation is required. The Validator
	// function is called *after* the MustChange logic, so if you wish to
	// fully handle validation, ensure MustChange is set to false.
	Validator Validator

	// Reset indicates that if the screen fails validation, this field should
	// always be reset to its original/default value, regardless of what the
	// user entered.
	Reset bool
}

FieldRules provides the validation rules for a particular field.

type Highlight

type Highlight byte

Highlight is a 3270 extended field attribute highlighting method

const (
	DefaultHighlight Highlight = 0
	Blink            Highlight = 0xf1
	ReverseVideo     Highlight = 0xf2
	Underscore       Highlight = 0xf4
)

The valid 3270 highlights

type Response

type Response struct {
	// Which Action ID key did the user press?
	AID AID

	// Row the cursor was on (0-based).
	Row int

	// Column the cursor was on (0-based).
	Col int

	// Field values.
	Values map[string]string
}

Response encapsulates data received from a 3270 client in response to the previously sent screen.

func HandleScreen

func HandleScreen(screen Screen, rules Rules, values map[string]string,
	pfkeys, exitkeys []AID, errorField string, crow, ccol int,
	conn net.Conn) (Response, error)

HandleScreen is a higher-level interface to the ShowScreen() function. HandleScreen will loop until all validation rules are satisfied, and only return when an expected AID (i.e. PF) key is pressed.

  • screen is the Screen to display (see ShowScreen()).
  • rules are the Rules to enforce: each key in the Rules map corresponds to a Field.Name in the screen array.
  • values are field values you wish to override (see ShowScreen()).
  • pfkeys and exitkeys are the AID keys that you wish to accept (that is, perform validation and return if successful) and treat as exit keys (unconditionally return).
  • errorField is the name of a field in the screen array that you wish error messages to be written in when HandleScreen loops waiting for a valid user submission.
  • crow and ccol are the initial cursor position.
  • conn is the network connection to the 3270 client.

HandleScreen will return when the user: 1) presses a key in pfkeys AND all fields pass validation, OR 2) the user presses a key in exitkeys. In all other cases, HandleScreen will re-present the screen to the user again, possibly with an error message set in the errorField field.

func ShowScreen

func ShowScreen(screen Screen, values map[string]string, crow, ccol int,
	conn net.Conn) (Response, error)

ShowScreen writes the 3270 datastream for the screen to a connection. Fields that aren't valid (e.g. outside of the 24x80 screen) are silently ignored. If a named field has an entry in the values map, the content of the field from the values map is used INSTEAD OF the Field struct's Content field. The values map may be nil if no overrides are needed. After writing the fields, the cursor is set to crow, ccol, which are 0-based positions: row 0-23 and col 0-79. Errors from conn.Write() are returned if encountered.

type Rules

type Rules map[string]FieldRules

Rules is a map of field names (strings) to FieldRules structs. Each field for which you wish validation to occur must appear in the map. Fields not in the map will not have any input validation performed.

type Screen

type Screen []Field

Screen is an array of Fields which compose a complete 3270 screen. No checking is performed for lack of overlapping fields, unique field names,

type Validator

type Validator func(input string) bool

Validator is a type that represents a function which can perform field input validation. The function is passed a string, input, and returns true if the input is valid or false if the not.

var IsInteger Validator = func(input string) bool {
	input = strings.TrimSpace(input)
	return isIntegerRegexp.MatchString(input)
}

IsInteger is a Validator that returns true if, after spaces are trimmed from the beginning and end if the string, the value is an integer (including negative numbers and 0).

var NonBlank Validator = func(input string) bool {
	return !(strings.TrimSpace(input) == "")
}

NonBlank is a Validator that returns true if, after spaces are trimmed from the beginning and end of the string, the value is not empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL