소스 검색

Initial commit

Viktor Grahn 7 년 전
커밋
c40f3e5532
4개의 변경된 파일291개의 추가작업 그리고 0개의 파일을 삭제
  1. 3 0
      .gitignore
  2. 27 0
      main.go
  3. 243 0
      oftp.go
  4. 18 0
      typedef.go

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+*.exe
+oftpTester
+*.json

+ 27 - 0
main.go

@@ -0,0 +1,27 @@
+package main
+
+import (
+  "os"
+  "fmt"
+)
+
+func main() {
+  if len(os.Args) != 2 {
+    fmt.Println("Usage:   oftpTester <profile-config>\nExample: oftpTester encodeChinet.json")
+    os.Exit(1)
+  }
+
+  var oftp Oftp
+
+  err := oftp.New(os.Args[1])
+  if err != nil {
+    fmt.Println(err)
+    os.Exit(2)
+  }
+
+  fmt.Printf("%+v\n", oftp)
+
+  err = oftp.Call()
+  fmt.Println(err)
+
+}

+ 243 - 0
oftp.go

@@ -0,0 +1,243 @@
+package main
+
+import (
+  "os"
+  "time"
+  "encoding/json"
+  "encoding/binary"
+  "net"
+  "fmt"
+  "errors"
+)
+
+func (o *Oftp) New(filename string) error {
+  // Set default values
+  newOftp := Oftp{
+    LocalCode: "LOCALCODE",
+    LocalPassword: "LOCALPWD",
+    PartnerCode: "1234567890CODE",
+    PartnerPassword: "SUPERSECRET",
+    OftpLevel: 4,
+    OftpBuffer: 512,
+    OftpDuplex: "S",
+    OftpCompression: "N",
+    OftpRestart: "N",
+    OftpCredit: 7,
+    OftpAuthentication: "N",
+    NetworkHost: "localhost",
+    NetworkPort: 3305,
+    NetworkTLS: false,
+  }
+
+  f, err := os.Open(filename)
+  if err != nil {
+    return err
+  }
+  defer f.Close()
+
+  d := json.NewDecoder(f)
+
+  if err := d.Decode(&newOftp); err != nil {
+    return err
+  }
+
+  *o = newOftp
+
+  return nil
+}
+
+func (o Oftp) Call() error {
+  // 1. Open connection
+  // 2. Wait for SSRM
+  // 3. Send SSID
+  // 4. Wait for SSID
+  // 5. Validate SSID
+  // 6. Send ESID
+
+  // 1. Open connection
+  addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", o.NetworkHost, o.NetworkPort))
+  if err != nil {
+    return err
+  }
+
+  conn, err := net.DialTCP("tcp", nil, addr)
+  if err != nil {
+    return err
+  }
+  defer conn.Close()
+
+  fmt.Printf("Connected to %s\n", addr.String())
+
+  // 2. Wait for SSRM
+  headerBuf := make([]byte, 4)
+  dataBuf := make([]byte, o.OftpBuffer)
+
+  // Read STH (header)
+  readCnt, err := conn.Read(headerBuf)
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  length, err := parseSTH(headerBuf[:4])
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  fmt.Printf("STH says STB is %d long\n", length)
+
+  // Read OFTP command
+  readCnt, err = conn.Read(dataBuf)
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  fmt.Printf("Read %d, should be %d\n", readCnt, length - 4)
+
+  if string(dataBuf[:readCnt]) != "IODETTE FTP READY \r" && string(dataBuf[:readCnt]) != "IODETTE FTP READY \n"{
+    conn.Close()
+    return errors.New(fmt.Sprintf("Expected SSRM (%x), got %x", "IODETTE FTP READY \r", dataBuf[:readCnt]))
+  }
+
+  // 3. Send SSID
+  fmt.Println(string(o.LocalSSID()))
+  writtenCnt, err := conn.Write(o.LocalSSID())
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  fmt.Printf("Write %d bytes to %s\n", writtenCnt, addr.String())
+
+  // 4. Wait for SSID
+  // Read STH (header)
+  readCnt, err = conn.Read(headerBuf)
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  length, err = parseSTH(headerBuf[:4])
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  fmt.Printf("STH says STB is %d long\n", length)
+
+  // Read OFTP command
+  readCnt, err = conn.Read(dataBuf)
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  fmt.Printf("Read %d, should be %d\n", readCnt, length - 4)
+
+  // 5. Validate SSID
+  ESIDCode := o.ValidateSSID(dataBuf[:readCnt]);
+  if ESIDCode < 0 {
+    // If ESID is received, disconnect
+    conn.Close()
+    return err
+  }
+
+  // 6. Send ESID
+  fmt.Println(string(o.ESID(ESIDCode)))
+  writtenCnt, err = conn.Write(o.ESID(ESIDCode))
+  if err != nil {
+    conn.Close()
+    return err
+  }
+
+  fmt.Printf("Write %d bytes to %s\n", writtenCnt, addr.String())
+
+  // Wait for partner to disconnect
+  conn.SetReadDeadline(time.Now().Add(10 * time.Second))
+  conn.Read(dataBuf)
+  conn.Close()
+  return nil
+}
+
+func (o Oftp) LocalSSID() []byte {
+  dataBuf := [61]byte{}
+  copy(dataBuf[0:1], "X")
+  copy(dataBuf[1:2], fmt.Sprintf("%d", o.OftpLevel))
+  copy(dataBuf[2:27], o.LocalCode)
+  copy(dataBuf[27:35], o.LocalPassword)
+  copy(dataBuf[35:40], fmt.Sprintf("%05d", o.OftpBuffer))
+  copy(dataBuf[40:41], o.OftpDuplex)
+  copy(dataBuf[41:42], o.OftpCompression)
+  copy(dataBuf[42:43], o.OftpRestart)
+  copy(dataBuf[43:44], "N")
+  copy(dataBuf[44:47], fmt.Sprintf("%03d", o.OftpCredit))
+  copy(dataBuf[47:48], o.OftpAuthentication)
+  copy(dataBuf[60:61], "\r")
+
+  sth := buildSTH(len(dataBuf))
+
+  stb := []byte{}
+
+  stb = append(stb, sth...)
+  stb = append(stb, dataBuf[:]...)
+
+  return stb
+}
+
+func (o Oftp) ESID(code int) []byte {
+  dataBuf := [7]byte{}
+  copy(dataBuf[0:1], "F")
+  copy(dataBuf[1:3], fmt.Sprintf("%02d", code))
+  copy(dataBuf[3:6], fmt.Sprintf("%03d", 0))
+  copy(dataBuf[6:7], "\r")
+
+  sth := buildSTH(len(dataBuf))
+  stb := []byte{}
+
+  stb = append(stb, sth...)
+  stb = append(stb, dataBuf[:]...)
+
+  return stb
+}
+
+func (o Oftp) ValidateSSID(SSIDBytes []byte) int {
+  // Validate cmd, code and password only
+  fmt.Println(string(SSIDBytes))
+  cmdByte := string(SSIDBytes[0:1])
+  if cmdByte != "X" {
+    return -1
+  }
+
+  codeBytes := string(SSIDBytes[2:27])
+  if codeBytes != fmt.Sprintf("%-25s", o.PartnerCode) {
+    return 3
+  }
+
+  passwordBytes := string(SSIDBytes[27:35])
+  if passwordBytes != fmt.Sprintf("%-8s", o.PartnerPassword) {
+    return 4
+  }
+
+  return 0
+
+}
+
+func parseSTH(sth []byte) (int32, error) {
+  sth[0] = 0
+  length := binary.BigEndian.Uint32(sth)
+  return int32(length), nil
+}
+
+func buildSTH(length int) []byte {
+  sth := make([]byte, 4)
+  sth[0] = 16
+
+  lengthBytes := make([]byte, 4)
+  binary.BigEndian.PutUint32(lengthBytes, uint32(length + 4))
+  copy(sth[1:4], lengthBytes[1:4])
+
+  return sth
+
+}

+ 18 - 0
typedef.go

@@ -0,0 +1,18 @@
+package main
+
+type Oftp struct {
+  LocalCode string `json:"LocalCode"`
+  LocalPassword string `json:"LocalPassword"`
+  PartnerCode string `json:"PartnerCode"`
+  PartnerPassword string `json:"PartnerPassword"`
+  OftpLevel int `json:"OftpLevel"`
+  OftpBuffer int `json:"OftpBuffer"`
+  OftpDuplex string `json:"OftpDuplex"`
+  OftpCompression string `json:"OftpCompression"`
+  OftpRestart string `json:"OftpRestart"`
+  OftpCredit int `json:"OftpCredit"`
+  OftpAuthentication string `json:"OftpAuthentication"`
+  NetworkHost string `json:"NetworkHost"`
+  NetworkPort int `json:"NetworkPort"`
+  NetworkTLS bool `json:"NetworkTLS"`
+}