[
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: gomod\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"20:00\"\n  open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/workflows/go.yml",
    "content": "on: [push, pull_request]\nname: Test\njobs:\n  test-linux:\n    strategy:\n      matrix:\n        go-version: [1.25.x, 1.26.x]\n    runs-on: ubuntu-latest\n    steps:\n      - name: Install Go\n        uses: actions/setup-go@v5\n        with:\n          go-version: ${{ matrix.go-version }}\n      - name: Checkout code\n        uses: actions/checkout@v1\n      - name: Run unit tests\n        run: go test ./...\n      - name: Run benchmark\n        run: go test -benchmem -bench . ./...\n      - name: Build GW Tester\n        run: |\n          go build -o sgw examples/gw-tester/sgw/*.go\n          go build -o pgw examples/gw-tester/pgw/*.go\n          go build -o mme examples/gw-tester/mme/*.go\n          go build -o enb examples/gw-tester/enb/*.go\n      - name: Run GW Tester\n        run: |\n          sudo ./sgw -config examples/gw-tester/sgw/sgw.yml &\n          sleep 1\n          sudo ./pgw -config examples/gw-tester/pgw/pgw.yml &\n          sleep 1\n          sudo ./mme -config examples/gw-tester/mme/mme.yml &\n          sleep 1\n          sudo ./enb -config examples/gw-tester/enb/enb.yml &\n          sleep 1\n      - name: Verify GW Tester is working\n        run: |\n          ENB=$(curl -sS http://127.0.10.1:58080/metrics)\n          [ \"$(echo \"$ENB\" | grep \"enb_active_sessions [0-9]\" | awk '{print $NF}' )\" == 5 ] || exit 101\n          MME=$(curl -sS http://127.0.10.2:58080/metrics)\n          [ \"$(echo \"$MME\" | grep \"mme_active_sessions [0-9]\" | awk '{print $NF}' )\" == 5 ] || exit 101\n          SGW=$(curl -sS http://127.0.10.3:58080/metrics)\n          [ \"$(echo \"$SGW\" | grep \"sgw_active_sessions [0-9]\" | awk '{print $NF}' )\" == 5 ] || exit 101\n          PGW=$(curl -sS http://127.0.10.4:58080/metrics)\n          [ \"$(echo \"$PGW\" | grep \"pgw_active_sessions [0-9]\" | awk '{print $NF}' )\" == 5 ] || exit 101\n  test-macos:\n    strategy:\n      matrix:\n        go-version: [1.25.x, 1.26.x]\n    runs-on: macos-latest\n    steps:\n      - name: Install Go\n        uses: actions/setup-go@v5\n        with:\n          go-version: ${{ matrix.go-version }}\n      - name: Checkout code\n        uses: actions/checkout@v1\n      - name: Setup loopback interface for tests\n        run: |\n          sudo ifconfig lo0 alias 127.0.0.2\n          sudo ifconfig lo0 alias 127.0.0.11\n          sudo ifconfig lo0 alias 127.0.0.12\n      - name: Test\n        run: go test $(go list ./... | grep -v '/examples')\n      - name: Bench\n        run: go test -benchmem -bench . $(go list ./... | grep -v '/examples')\n  # test-windows:\n  #   strategy:\n  #     matrix:\n  #       go-version: [1.25.x, 1.26.x]\n  #   runs-on: windows-latest\n  #   steps:\n  #   - name: Install Go\n  #     uses: actions/setup-go@v5\n  #     with:\n  #       go-version: ${{ matrix.go-version }}\n  #   - name: Checkout code\n  #     uses: actions/checkout@v1\n  #   - name: Test\n  #     run: go test ./...\n  #   - name: Bench\n  #     run: go test -benchmem -bench . ./...\n"
  },
  {
    "path": ".github/workflows/golangci-lint.yml",
    "content": "name: golangci-lint\non:\n  push:\n    tags:\n      - v*\n    branches:\n      - main\n  pull_request:\njobs:\n  golangci:\n    name: lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-go@v6\n        with:\n          go-version-file: 'go.mod'\n          cache: true\n      - name: golangci-lint\n        uses: golangci/golangci-lint-action@v9\n        with:\n          version: latest\n"
  },
  {
    "path": ".gitignore",
    "content": "examples/mme/mme\nexamples/pgw/pgw\nexamples/sgw/sgw\nexamples/gw-tester/enb/enb\nexamples/gw-tester/pgw/pgw\nexamples/gw-tester/sgw/sgw\nexamples/gw-tester/mme/mme\n\n**/testdata/\n"
  },
  {
    "path": ".golangci.yml",
    "content": "version: \"2\"\nrun:\n  issues-exit-code: 1\n  tests: false\nlinters:\n  default: none\n  enable:\n    - asciicheck\n    - bodyclose\n    - dogsled\n    - errcheck\n    - errorlint\n    - goconst\n    - gocritic\n    - gomodguard\n    - goprintffuncname\n    - gosec\n    - govet\n    - ineffassign\n    - misspell\n    - nakedret\n    - prealloc\n    - rowserrcheck\n    - staticcheck\n    - unconvert\n    - unparam\n    - unused\n  settings:\n    gosec:\n      excludes:\n        - G115\n  exclusions:\n    generated: lax\n    presets:\n      - comments\n      - common-false-positives\n      - legacy\n      - std-error-handling\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\nissues:\n  max-issues-per-linter: 4095\n  max-same-issues: 1023\n  new: true\nformatters:\n  enable:\n    - gofmt\n    - goimports\n  exclusions:\n    generated: lax\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019-2025 Yoshiyuki Kurauchi\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# go-gtp: GTP in Go\n\nPackage gtp provides simple and painless handling of GTP (GPRS Tunneling Protocol) in the Go programming language.\n\n![CI status](https://github.com/wmnsk/go-gtp/actions/workflows/go.yml/badge.svg)\n[![golangci-lint](https://github.com/wmnsk/go-gtp/actions/workflows/golangci-lint.yml/badge.svg)](https://github.com/wmnsk/go-gtp/actions/workflows/golangci-lint.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/wmnsk/go-gtp.svg)](https://pkg.go.dev/github.com/wmnsk/go-gtp)\n[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/wmnsk/go-gtp/blob/main/LICENSE)\n\n## Project Status\n\nThis project is still EXPERIMENTAL.  \nAny part of the implementations (including exported APIs) may be changed before released as v1.0.0.\n\n## Features\n\n* Flexible enough to control everything in the GTP protocol, making it suitable for developing mobile core network nodes or testing tools for them.\n* Provides many helpers that are kind to developers, such as session, bearer, and TEID management.\n* Makes it easy to handle multiple connections with fixed IP and Port with UDP (or other `net.PacketConn`).\n* Currently works only on Linux and macOS since netlink support is introduced. However, the plan is to make it work on Windows in the future.\n\n## Getting Started\n\n### Prerequisites\n\ngo-gtp supports Go Modules. Run `go mod tidy` in your project's directory to collect the required packages automatically.\n\n```\ngo mod tidy\n```\n\n_This project follows [the Release Policy of Go](https://golang.org/doc/devel/release.html#policy)._\n\n### Running examples\n\n#### End-to-end\n\nWe have a set of tools called GW Tester at [`examples/gw-tester`](./examples/gw-tester). See the [document](./examples/gw-tester/README.md) for how it works and how to run it. It is also used for the integration test of this project. [Workflow setting](./.github/workflows/go.yml) may help you understand it as well.\n\n#### Individual node\n\n[The examples](examples/) work as it is by `go build` and executing commands in the following way.\n\n*Note for macOS users*: before running any go service, make sure to execute `./mac_local_host_enabler.sh` you will find at [examples/utils](examples/utils).\n\n1. Open four terminals on a machine and start capturing on the loopback interface.\n\n2. Start P-GW on terminal #1 and #2\n```shell-session\n// on terminal #1\n./pgw\n\n// on terminal #2\n./pgw -s5c 127.0.0.53 -s5u 127.0.0.5\n```\n\n3. Start S-GW on terminal #3\n\n```shell-session\n// on terminal #3\n./sgw\n```\n\n4. Start MME on terminal #4\n\n```shell-session\n// on terminal #4\n./mme\n```\n\n5. You will see the nodes exchanging Create Session and Modify Bearer on C-Plane, and ICMP Echo on U-Plane afterwards.\n\n_The \"mme\" is not an MME per se. In addition to S11 interface, it also mocks UEs and an eNB to establish sessions and send packets on U-Plane._\n\n## Developing with go-gtp\n\nThis section briefly describes how to develop your own GTP node with go-gtp.\nFor the detailed usage of a specific version, see README.md under each version's directory.\n\n| Version | Details                      |\n| ------- | ---------------------------- |\n| GTPv0   | [README.md](gtpv0/README.md) |\n| GTPv1   | [README.md](gtpv1/README.md) |\n| GTPv2   | [README.md](gtpv2/README.md) |\n\n### Establishing a connection between nodes\n\nEach version has `net.PacketConn`-like APIs and GTP-specific ones, which are often version-specific.\nThe basic idea behind the current implementation is;\n\n* `Dial` or `ListenAndServe` to create a connection (`Conn`) between nodes.\n* Register handlers to the `Conn` for specific messages with `AddHandler`, allowing users to handle the messages coming from the remote endpoint as flexible as possible, with less pain.\n* `CreateXXX` to create session or PDP context with arbitrary IEs given. Session/PDP context is structured, and they also have some helpers like `AddTEID` to handle known TEID properly.\n\n### Handling messages and IEs\n\n#### Messages\n\nAll the messages implement the same interface: `message.Message`, and have their own structs named `<MessageName>`, which can be created by `New<MessageName>` with given `ie.IE`s. `message.Message` can be sent on top of `Conn` with `SendMessageTo`, or can be serialized into `[]byte` with `Marshal`.\n\nTo parse the message from `[]byte`, use `message.Parse`. The parsed message will be one of the structs that implement `message.Message`, and you can type-assert it to the corresponding struct to access the fields which are a set of `ie.IE`s.\n\n#### IEs\n\nAll the IEs are of the same type: `ie.IE` (not an interface). An IE can be created either with `New<IEName>`, with `ie.New`, or with `ie.New<TypeIE>`. The latter two are useful when you want to create an IE with an unsupported type or our constructor does not work well for you.\n\nTo parse the IE from `[]byte`, use `ie.Parse` (note that `message.Parse` parses all the IEs on a message - you don't need to call `ie.Parse` when you're handling IEs on a message). The value of the parsed `ie.IE` can be retrieved with `<IEName>`, `ValueAs<IEType>`. Some of the complicated IEs have their own struct named `<IEName>Fields` to get the values by accessing the fields.\n\nFor grouped IEs, accesing the `ChildIEs` field and iterating over the list of IEs contained is the most efficient way in most cases. Though there are the methods to get the specific IE value from the list (e.g., `BearerFlags` can be called upon `BearerContext` IE), they are not recommended since they always parse the whole list of IEs again.\n\n## Supported Features\n\nNote that \"supported\" means that the package provides helpers that make it easier to handle.\nIn other words, even if a message/IE is not marked as \"Yes\", you can make it work with some additional effort.\n\nYour contribution is welcome to implement helpers for all the types, of course!\n\n| Version           | Messages | IEs  | Networking (state machine)                  | Details                                                  |\n| ----------------- | -------- | ---- | ------------------------------------------- | -------------------------------------------------------- |\n| GTPv0             | ~35%     | ~80% | not implemented yet                         | [gtpv0/README](gtpv0/README.md#supported-features) |\n| GTPv1             | ~25%     | ~30% | v1-U: functional <br> v1-C: not implemented | [gtpv1/README](gtpv1/README.md#supported-features) |\n| GTPv2             | ~40.0%   | ~45% | functional                                  | [gtpv2/README](gtpv2/README.md#supported-features) |\n| GTP' <br> (Prime) | N/A      | N/A  | N/A                                         | _not planned_                                            |\n\n_You may also be interested in the sibling project [go-pfcp](https://github.com/wmnsk/go-pfcp) which is a PFCP implementation in Go._\n\n## Contributing\n\nWith the design goal of being flexible and easy to use, go-gtp is still in the early stage of development. Any contribution is welcome! Please feel free to open an issue or a pull request.\n\nPlease don't forget to run tests once you are done with your changes. Additionally, running the fuzz test is recommended to make sure that the implementation is robust enough.\n\n```shell-session\ngo test ./...\ngo test -fuzz .\n```\n\n*Note for macOS users*: the first time you run any test, make sure to execute `./mac_local_host_enabler.sh` you will find at [examples/utils](examples/utils). You will have to run the script again after each reboot.\n\n## Authors\n\n[Yoshiyuki Kurauchi](https://wmnsk.com/) and [contributors](https://github.com/wmnsk/go-gtp/graphs/contributors).\n\n## LICENSE\n\n[MIT](https://github.com/wmnsk/go-gtp/blob/main/LICENSE)\n"
  },
  {
    "path": "doc.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package gtp provides simple and painless handling of GTP (GPRS Tunneling Protocol).\n//\n// This package is the wrapper for all versions of GTP.  Please see the godocs of each version instead.\n//\n// GTPv0: https://pkg.go.dev/github.com/wmnsk/go-gtp/v0\n//\n// GTPv1: https://pkg.go.dev/github.com/wmnsk/go-gtp/v1\n//\n// GTPv2: https://pkg.go.dev/github.com/wmnsk/go-gtp/v2\n//\n// Please also see README.md for detailed usage of the APIs provided by this package,\n// as well as how to run the examples.\n//\n// https://github.com/wmnsk/go-gtp/blob/main/README.md\n//\n// https://github.com/wmnsk/go-gtp/tree/main/examples/gw-tester\npackage gtp\n"
  },
  {
    "path": "errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtp\n\nimport \"errors\"\n\n// Common error definitions.\nvar (\n\tErrInvalidVersion    = errors.New(\"got invalid version\")\n\tErrInvalidLength     = errors.New(\"length value is invalid\")\n\tErrTooShortToParse   = errors.New(\"too short to decode as GTP\")\n\tErrTooShortToMarshal = errors.New(\"too short to serialize\")\n)\n"
  },
  {
    "path": "examples/gw-tester/README.md",
    "content": "# GW Tester\n\nA pseudo eNB and MME as a tester for S/P-GW.\n\n## What's this?\n\n![diagram](./docs/diagram.png)\n\nIt is a burden to use actual UE/eNB/MME just to test S/P-GW, isn't it?  \nGW Tester emulates the minimal required behavior of surrounding nodes to perform quick and simple testing on S/P-GW.\n\nA blog post by the author is available [here](https://wmnsk.com/posts/20200116_gw-tester/) for those who are interested in :)  \n_NOTE: Some of the blog post's configurations or codes might be no longer relevant in the current version._\n\n## How it works\n\n### Authentication\n\nNothing!  \nSubscribers defined in the `enb.yml` file can immediately attach and use the created sessions. MME accepts any subscribers without an authentication procedure.\nCommunication over the S1-MME interface is done with protobuf/gRPC instead of the S1AP protocol.\n\n```\n=== AD ===\nLooking for a Go package for LTE authentication?\nMILENAGE algorithm implementation is available :)\n\nhttps://github.com/wmnsk/milenage\n```\n\n### Gateway Selection\n\nNo DNS lookup by TAI/APN is implemented.\nMME just chooses gateways according to the mapping of source IP ranges and GW's IPs defined in `mme.yml`. This behavior might be changed in the future.\n\n### Session Establishment\n\nMME exchanges the real GTPv2 session establishment messages like Create/Modify/Delete Session with S-GW.\n\n* IP address assignment  \nCurrently, we use the IP address that is defined in `enb.yml`, and the one passed by P-GW is ignored. This behavior might be changed in the future to be more practical.\n\n* TEID allocation  \nIt can be both static and dynamic. Random TEID will be allocated by enb if `i_tei` in `enb.yml` is set to `0`. For outgoing TEID, the one that S-GW allocates will be used.\n\n### U-Plane Data Injection\n\neNB forwards incoming traffic from UE or generates traffic by itself depending on the `type` in `enb.yml`.\nGTP-U feature is based on [Linux Kernel GTP-U](https://www.kernel.org/doc/Documentation/networking/gtp.txt) with netlink.\n\n| type     | behavior                                                                                                        |\n| -------- | --------------------------------------------------------------------------------------------------------------- |\n| external | eNB encapsulates and forwards the incoming packets from `src_ip` toward the specified interface(`euu_if_name`). |\n| http_get | eNB starts sending HTTP GET to the specified URL.                                                               |\n| ...      | _(other types might be implemented in the future!)_                                                             |\n\n## Getting Started\n\n### Prerequisites\n\n* Linux (kernel >= 4.12) with root privilege\n* `net.ip_forward` enabled\n* ports opened: 36412/TCP, 2123/UDP, 2152/UDP\n\n### Run testers\n\nJust `go get` eNB and MME.\nFunctional S-GW and P-GW are also available in the same directory if you need them.\n\n```shell-session\ngo get github.com/wmnsk/go-gtp/examples/gw-tester/enb\ngo get github.com/wmnsk/go-gtp/examples/gw-tester/mme\n```\n\nAnd run them with YAML configuration. See [Configuration](#configurations) section for details.\n\n```shell-session\n./mme\n```\n\n```shell-session\n./enb\n```\n\nThen you'll see;\n\n* MME starts sending GTPv2 Create Session Request to S-GW after it receives subscriber information from eNB.\n* When sessions are successfully created on S/P-GW, eNB sets up GTP-U tunnels with S-GW.\n\nAfter the successful creation of the sessions, you can inject packets externally or generate them on eNB.\n\n## Configurations\n\nEach node has a YAML file as a configuration.  \nIn general, config consists of the network information of local/remote nodes and some node-specific parameters.\n\n### eNB\n\n#### Global\n\nThese values are used to identify eNB. Some of them are just to be set inside the packets and not validated.\n\n| config           | type of value | description                                                       |\n| ---------------- | ------------- | ----------------------------------------------------------------- |\n| `mcc`            | string        | MCC of eNB                                                        |\n| `mnc`            | string        | MNC of eNB                                                        |\n| `rat_type`       | uint8         | RAT Type (`6` for E-UTRAN)                                        |\n| `tai`            | uint16        | TAI of eNB                                                        |\n| `eci`            | uint32        | ECI of eNB                                                        |\n| `mme_addr`       | string        | IP/Port of MME to dial, for S1-MME interface                      |\n| `use_kernel_gtp` | bool          | Use Kernel GTP or not. U-Plane does not work when set to `false`. |\n| `prom_addr`      | string        | IP/Port of MME to serve Prometheus                                |\n\n#### Local Addresses\n\n`local_addresses` are the IP addresses/ports to be bound on the local machine.\n\n| config   | type of value | description                   |\n| -------- | ------------- | ----------------------------- |\n| `s1c_ip` | string        | local IP for S1-MME interface |\n| `s1u_ip` | string        | local IP for S1-U interface   |\n\n#### Subscribers\n\n`subscribers` are the list of subscribers to attach.\n\n| config               | type of value | description                                                                                                                                                                     |\n| -------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `imsi`               | string        | IMSI of the subscriber                                                                                                                                                          |\n| `msisdn`             | string        | MSISDN of the subscriber                                                                                                                                                        |\n| `imeisv`             | string        | IMEISV of the subscriber                                                                                                                                                        |\n| `src_ip`             | string        | source IP of the subscriber (not assigned by P-GW)                                                                                                                              |\n| `i_tei`              | uint32        | incoming TEID that S-GW should specify the subscriber                                                                                                                           |\n| `type`               | string        | `external` or `http_get`. see [U-Plane Data Injection](#u-plane-data-injection)                                                                                                 |\n| `euu_if_name`        | string        | name of the network interface on eUu side.</br>type=`external`: Used to receive traffic from external UE</br>type=`http_get`: Used as a source interface that `src_ip` is added |\n| `http_url`           | string        | URL to HTTP GET by built-in traffic generator                                                                                                                                   |\n| `reattach_on_reload` | bool          | whether to perform the attach procedure again on config reload                                                                                                                  |\n\n### MME\n\n#### Global\n\nThese values are used to identify MME. Some of them are just to be set inside the packets and not validated.\n\n| config      | type of value | description                        |\n| ----------- | ------------- | ---------------------------------- |\n| `mcc`       | string        | MCC of MME                         |\n| `mnc`       | string        | MNC of MME                         |\n| `apn`       | string        | APN assigned to all the subscriber |\n| `prom_addr` | string        | IP/Port of MME to serve Prometheus |\n\n#### Local Addresses\n\n`local_addresses` are the IP addresses/ports to be bound on the local machine.\n\n| config     | type of value | description                        |\n| ---------- | ------------- | ---------------------------------- |\n| `s1c_addr` | string        | local IP/Port for S1-MME interface |\n| `s11_ip`   | string        | local IP for S11 interface         |\n\n#### Gateway IPs\n\nIP addresses required to know/tell S-GW. This is typically done by DNS lookup with APN, but it's static for now.\n\n| config       | type of value | description                  |\n| ------------ | ------------- | ---------------------------- |\n| `sgw_s11_ip` | string        | S-GW's IP for S11 interface  |\n| `pgw_s5c_ip` | string        | P-GW's IP for S5-C interface |\n\n### S-GW\n\n#### Local Addresses\n\n`local_addresses` are the IP addresses/ports to be bound on the local machine.\n\n| config           | type of value | description                         |\n| ---------------- | ------------- | ----------------------------------- |\n| `s11_ip`         | string        | local IP for S11 interface          |\n| `s1u_ip`         | string        | local IP for S1-U interface         |\n| `s5c_ip`         | string        | local IP for S5-C interface         |\n| `s5u_ip`         | string        | local IP for S5-U interface         |\n| `use_kernel_gtp` | bool          | Use Kernel GTP or not.              |\n| `prom_addr`      | string        | IP/Port of S-GW to serve Prometheus |\n\n### P-GW\n\n#### Global\n\n| config           | type of value | description                                                                |\n| ---------------- | ------------- | -------------------------------------------------------------------------- |\n| `sgi_if_name`    | string        | name of the network interface on SGi side. Used to downlink route traffic. |\n| `route_subnet`   | string        | IP subnet of UEs that should be routed properly.                           |\n| `use_kernel_gtp` | bool          | Use Kernel GTP or not. U-Plane does not work when set to `false`.          |\n| `prom_addr`      | string        | IP/Port of P-GW to serve Prometheus                                        |\n\n#### Local Addresses\n\n`local_addresses` are the IP addresses/ports to be bound on the local machine.\n\n| config   | type of value | description                 |\n| -------- | ------------- | --------------------------- |\n| `s5c_ip` | string        | local IP for S5-C interface |\n| `s5u_ip` | string        | local IP for S5-U interface |\n| `sgi_ip` | string        | local IP for SGi interface  |\n\n## Other Features\n\n### Reloading config\n\nThe programs can handle `SIGHUP` to reload config without deleting sessions. Update YAML file and send `SIGHUP` to the process.\n\n### Instrumentation\n\nGW Tester nodes expose some metrics for Prometheus if `prom_addr` is given in each config. You can see the sample response from each node in [this Gist](https://gist.github.com/wmnsk/72f6d2d2450452090cd6351ffe63f660).  \nI'm planning to add some more metrics like \"success rate of HTTP probe\", etc.\n\n| Metrics           | Name                                  | Description                                   |\n| ----------------- | ------------------------------------- | --------------------------------------------- |\n| Active sessions   | `<node-name>_active_sessions`         | number of session established currently       |\n| Active bearers    | `<node-name>_active_bearers`          | number of GTP-U tunnels established currently |\n| Messages sent     | `<node-name>_messages_sent_total`     | number of messages sent by messagge type      |\n| Messages received | `<node-name>_messages_received_total` | number of messages received by messagge type  |\n"
  },
  {
    "path": "examples/gw-tester/enb/config.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\n\t\"gopkg.in/yaml.v2\"\n)\n\n// Config is a configurations loaded from yaml.\ntype Config struct {\n\tLocalAddrs struct {\n\t\tS1CIP string `yaml:\"s1c_ip\"`\n\t\tS1UIP string `yaml:\"s1u_ip\"`\n\t} `yaml:\"local_addresses\"`\n\n\tMMEAddr  string `yaml:\"mme_addr\"`\n\tPromAddr string `yaml:\"prom_addr\"`\n\n\tMCC          string        `yaml:\"mcc\"`\n\tMNC          string        `yaml:\"mnc\"`\n\tRATType      uint8         `yaml:\"rat_type\"`\n\tTAI          uint16        `yaml:\"tai\"`\n\tECI          uint32        `yaml:\"eci\"`\n\tSubscribers  []*Subscriber `yaml:\"subscribers\"`\n\tUseKernelGTP bool          `yaml:\"use_kernel_gtp\"`\n}\n\n// Subscriber represents a subscriber.\ntype Subscriber struct {\n\tIMSI   string `yaml:\"imsi\"`\n\tMSISDN string `yaml:\"msisdn\"`\n\tIMEISV string `yaml:\"imeisv\"`\n\tSrcIP  string `yaml:\"src_ip\"`\n\tITEI   uint32 `yaml:\"i_tei\"`\n\n\tTrafficType string `yaml:\"type\"`\n\tEUuIFName   string `yaml:\"euu_if_name\"`\n\tHTTPURL     string `yaml:\"http_url\"`\n\n\tReattach bool `yaml:\"reattach_on_reload\"`\n\n\t// values for these fields are given from MME.\n\tsgwAddr string\n\totei    uint32\n}\n\n// String returns the information of s in string.\nfunc (s *Subscriber) String() string {\n\treturn fmt.Sprintf(\n\t\t\"IMSI: %s, MSISDN: %s, IMEISV: %s, SrcIP: %s, S-GW: %s, I_TEI: %#08x, O_TEI: %#08x\",\n\t\ts.IMSI, s.MSISDN, s.IMEISV, s.SrcIP, s.sgwAddr, s.ITEI, s.otei,\n\t)\n}\n\nfunc loadConfig(path string) (*Config, error) {\n\tbuf, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tc := &Config{}\n\tif err := yaml.Unmarshal(buf, c); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n"
  },
  {
    "path": "examples/gw-tester/enb/enb.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n\t\"github.com/vishvananda/netlink\"\n\t\"google.golang.org/grpc\"\n\n\t\"github.com/wmnsk/go-gtp/examples/gw-tester/s1mme\"\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n)\n\ntype enb struct {\n\tmu sync.Mutex\n\n\t// S1-MME\n\tmmeAddr     net.Addr\n\tcConn       *grpc.ClientConn\n\ts1mmeClient s1mme.AttacherClient\n\n\t// S1-U\n\tuAddr net.Addr\n\tuConn *gtpv1.UPlaneConn\n\n\tlocation *s1mme.Location\n\n\tcandidateSubs []*Subscriber\n\tsessions      []*Subscriber\n\tattachCh      chan *Subscriber\n\n\tuseKernelGTP bool\n\n\taddedAddrs  map[netlink.Link]*netlink.Addr\n\taddedRoutes []*netlink.Route\n\taddedRules  []*netlink.Rule\n\n\tpromAddr string\n\tmc       *metricsCollector\n\n\terrCh chan error\n}\n\nfunc newENB(cfg *Config) (*enb, error) {\n\te := &enb{\n\t\tmu: sync.Mutex{},\n\t\tlocation: &s1mme.Location{\n\t\t\tMcc:     cfg.MCC,\n\t\t\tMnc:     cfg.MNC,\n\t\t\tRatType: s1mme.Location_RATType(cfg.RATType),\n\t\t\tTai:     uint32(cfg.TAI),\n\t\t\tEci:     cfg.ECI,\n\t\t},\n\t\tcandidateSubs: cfg.Subscribers,\n\t\tuseKernelGTP:  cfg.UseKernelGTP,\n\t\taddedAddrs:    make(map[netlink.Link]*netlink.Addr),\n\n\t\terrCh: make(chan error, 1),\n\t}\n\n\tvar err error\n\te.uAddr, err = net.ResolveUDPAddr(\"udp\", cfg.LocalAddrs.S1UIP+gtpv1.GTPUPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\te.mmeAddr, err = net.ResolveTCPAddr(\"tcp\", cfg.MMEAddr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif cfg.PromAddr != \"\" {\n\t\t// validate if the address is valid or not.\n\t\tif _, err = net.ResolveTCPAddr(\"tcp\", cfg.PromAddr); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\te.promAddr = cfg.PromAddr\n\t}\n\n\tif !e.useKernelGTP {\n\t\tlog.Println(\"WARN: U-Plane does not work without GTP kernel module\")\n\t}\n\n\treturn e, nil\n}\n\nfunc (e *enb) run(ctx context.Context) error {\n\t// TODO: bind local address(cfg.LocalAddrs.S1CIP) with WithDialer option?\n\tconn, err := grpc.Dial(e.mmeAddr.String(), grpc.WithInsecure())\n\tif err != nil {\n\t\treturn err\n\t}\n\te.s1mmeClient = s1mme.NewAttacherClient(conn)\n\tlog.Printf(\"Established S1-MME connection with %s\", e.mmeAddr)\n\n\te.uConn = gtpv1.NewUPlaneConn(e.uAddr)\n\tif e.useKernelGTP {\n\t\tif err := e.uConn.EnableKernelGTP(\"gtp-enb\", gtpv1.RoleSGSN); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tgo func() {\n\t\tif err := e.uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t\tlog.Println(\"uConn.ListenAndServe exitted\")\n\t}()\n\tlog.Printf(\"Started serving S1-U on %s\", e.uAddr)\n\n\t// start serving Prometheus, if address is given\n\tif e.promAddr != \"\" {\n\t\tif err := e.runMetricsCollector(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\thttp.Handle(\"/metrics\", promhttp.Handler())\n\t\tgo func() {\n\t\t\tif err := http.ListenAndServe(e.promAddr, nil); err != nil {\n\t\t\t\tlog.Println(err)\n\t\t\t}\n\t\t}()\n\t\tlog.Printf(\"Started serving Prometheus on %s\", e.promAddr)\n\t}\n\n\tfor _, sub := range e.candidateSubs {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase <-time.After(10 * time.Millisecond):\n\t\t\t// not to load too much in case of many subscribers\n\t\t}\n\n\t\tif err := e.attach(ctx, sub); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// wait for new subscribers to be attached\n\te.attachCh = make(chan *Subscriber)\n\tdefer close(e.attachCh)\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase sub := <-e.attachCh:\n\t\t\tgo func() {\n\t\t\t\tif err := e.attach(ctx, sub); err != nil {\n\t\t\t\t\tlog.Printf(\"Failed to attach: %s: %s\", sub, err)\n\t\t\t\t}\n\t\t\t}()\n\t\t\t// wait 10ms after dispatching\n\t\t\ttime.Sleep(10 * time.Millisecond)\n\t\t}\n\t}\n}\n\nfunc (e *enb) reload(cfg *Config) error {\n\te.location = &s1mme.Location{\n\t\tMcc:     cfg.MCC,\n\t\tMnc:     cfg.MNC,\n\t\tRatType: s1mme.Location_RATType(cfg.RATType),\n\t\tTai:     uint32(cfg.TAI),\n\t\tEci:     cfg.ECI,\n\t}\n\n\t// TODO: consider more efficient way\n\tvar attachSubs []*Subscriber\n\tfor _, sub := range cfg.Subscribers {\n\t\tvar existing bool\n\t\tfor _, attached := range e.sessions {\n\t\t\tif sub.IMSI == attached.IMSI {\n\t\t\t\texisting = true\n\t\t\t}\n\t\t}\n\n\t\tif existing {\n\t\t\tif !sub.Reattach {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif err := e.uConn.DelTunnelByITEI(sub.ITEI); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tattachSubs = append(attachSubs, sub)\n\t}\n\n\tfor _, sub := range attachSubs {\n\t\te.attachCh <- sub\n\t}\n\treturn nil\n}\n\nfunc (e *enb) close() error {\n\tvar errs []error\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\n\tfor l, a := range e.addedAddrs {\n\t\tif err := netlink.AddrDel(l, a); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tfor _, r := range e.addedRoutes {\n\t\tif err := netlink.RouteDel(r); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tfor _, r := range e.addedRules {\n\t\tif err := netlink.RuleDel(r); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif c := e.uConn; c != nil {\n\t\tif err := c.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\tif c := e.cConn; c != nil {\n\t\tif err := c.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\treturn fmt.Errorf(\"errors while closing eNB: %v\", errs)\n}\n\nfunc (e *enb) attach(ctx context.Context, sub *Subscriber) error {\n\t// allocate random TEID if 0 is specified in config.\n\tif sub.ITEI == 0 {\n\t\tsub.ITEI = e.newTEID()\n\t}\n\n\treq := &s1mme.AttachRequest{\n\t\tImsi:     sub.IMSI,\n\t\tMsisdn:   sub.MSISDN,\n\t\tImeisv:   sub.IMEISV,\n\t\tS1UAddr:  e.uConn.LocalAddr().String(),\n\t\tSrcIp:    sub.SrcIP,\n\t\tITei:     sub.ITEI,\n\t\tLocation: e.location,\n\t}\n\n\trsp, err := e.s1mmeClient.Attach(ctx, req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif e.mc != nil {\n\t\te.mc.messagesSent.WithLabelValues(e.mmeAddr.String(), \"Attach Request\").Inc()\n\t\te.mc.messagesReceived.WithLabelValues(e.mmeAddr.String(), \"Attach Response\").Inc()\n\t}\n\n\tswitch rsp.Cause {\n\tcase s1mme.Cause_SUCCESS:\n\t\tsgwIP, _, err := net.SplitHostPort(rsp.SgwAddr)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif e.useKernelGTP {\n\t\t\tif err := e.uConn.AddTunnelOverride(\n\t\t\t\tnet.ParseIP(sgwIP), net.ParseIP(req.SrcIp), rsp.OTei, req.ITei,\n\t\t\t); err != nil {\n\t\t\t\tlog.Println(net.ParseIP(sgwIP), net.ParseIP(req.SrcIp), rsp.OTei, req.ITei)\n\t\t\t\te.errCh <- fmt.Errorf(\"failed to create tunnel for %s: %w\", sub.IMSI, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif err := e.addRoute(); err != nil {\n\t\t\t\te.errCh <- fmt.Errorf(\"failed to add route for %s: %w\", sub.IMSI, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\n\t\tsub.sgwAddr = rsp.SgwAddr\n\t\tsub.otei = rsp.OTei\n\n\t\te.sessions = append(e.sessions, sub)\n\t\tif e.useKernelGTP {\n\t\t\tif err := e.setupUPlane(ctx, sub); err != nil {\n\t\t\t\te.errCh <- fmt.Errorf(\"failed to setup U-Plane for %s: %w\", sub.IMSI, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tlog.Printf(\"Successfully established tunnel for %s\", sub.IMSI)\n\t\t}\n\tdefault:\n\t\te.errCh <- fmt.Errorf(\"got unexpected Cause for %s: %s\", rsp.Cause, sub.IMSI)\n\t\treturn nil\n\t}\n\n\treturn nil\n}\n\nfunc (e *enb) newTEID() uint32 {\n\tb := make([]byte, 4)\n\tif _, err := rand.Read(b); err != nil {\n\t\treturn 0\n\t}\n\n\tgenerated := binary.BigEndian.Uint32(b)\n\tfor _, s := range e.sessions {\n\t\tif generated == s.ITEI {\n\t\t\treturn e.newTEID()\n\t\t}\n\t}\n\n\treturn generated\n}\n\nfunc (e *enb) setupUPlane(ctx context.Context, sub *Subscriber) error {\n\tswitch sub.TrafficType {\n\tcase \"http_get\":\n\t\tif err := e.addIP(sub); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := e.addRuleLocal(sub); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tgo func() {\n\t\t\tif err := e.runHTTPProbe(ctx, sub); err != nil {\n\t\t\t\te.errCh <- err\n\t\t\t}\n\t\t}()\n\tcase \"external\":\n\t\tif err := e.addRuleExternal(sub); err != nil {\n\t\t\treturn err\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown/unimplemented type: %s specified for 'type' in subscriber\", sub.TrafficType)\n\t}\n\n\treturn nil\n}\n\nfunc (e *enb) addRoute() error {\n\troute := &netlink.Route{\n\t\tDst:       &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)}, // default\n\t\tLinkIndex: e.uConn.KernelGTP.Link.Attrs().Index,                    // dev gtp-<ECI>\n\t\tScope:     netlink.SCOPE_LINK,                                      // scope link\n\t\tProtocol:  4,                                                       // proto static\n\t\tPriority:  1,                                                       // metric 1\n\t\tTable:     1001,                                                    // table <ECI>\n\t}\n\n\te.addedRoutes = append(e.addedRoutes, route)\n\treturn netlink.RouteReplace(route)\n}\n\nfunc (e *enb) addRuleExternal(sub *Subscriber) error {\n\trules, err := netlink.RuleList(0)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmask32 := &net.IPNet{IP: net.ParseIP(sub.SrcIP), Mask: net.CIDRMask(32, 32)}\n\tfor _, r := range rules {\n\t\tif r.IifName == sub.EUuIFName && r.Src == mask32 && r.Table == 1001 {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\trule := netlink.NewRule()\n\trule.IifName = sub.EUuIFName\n\trule.Src = mask32\n\trule.Table = 1001\n\n\te.addedRules = append(e.addedRules, rule)\n\treturn netlink.RuleAdd(rule)\n}\n\nfunc (e *enb) addRuleLocal(sub *Subscriber) error {\n\trules, err := netlink.RuleList(0)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmask32 := &net.IPNet{IP: net.ParseIP(sub.SrcIP), Mask: net.CIDRMask(32, 32)}\n\tfor _, r := range rules {\n\t\tif r.Src == mask32 && r.Table == 1001 {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\trule := netlink.NewRule()\n\trule.Src = mask32\n\trule.Table = 1001\n\n\te.addedRules = append(e.addedRules, rule)\n\treturn netlink.RuleAdd(rule)\n}\n\nfunc (e *enb) runHTTPProbe(ctx context.Context, sub *Subscriber) error {\n\tladdr, err := net.ResolveTCPAddr(\"tcp\", sub.SrcIP+\":0\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdialer := net.Dialer{LocalAddr: laddr}\n\tclient := http.Client{\n\t\tTransport: &http.Transport{Dial: dialer.Dial},\n\t\tTimeout:   3 * time.Second,\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase <-time.After(5 * time.Second):\n\t\t\t// do nothing here and go forward\n\t\t}\n\n\t\trsp, err := client.Get(sub.HTTPURL)\n\t\tif err != nil {\n\t\t\te.errCh <- fmt.Errorf(\"failed to GET %s: %w\", sub.HTTPURL, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tif rsp.StatusCode == http.StatusOK {\n\t\t\tlog.Printf(\"[HTTP Probe;%s] Successfully GET %s: Status: %s\", sub.IMSI, sub.HTTPURL, rsp.Status)\n\t\t\trsp.Body.Close()\n\t\t\tcontinue\n\t\t}\n\t\trsp.Body.Close()\n\t\te.errCh <- fmt.Errorf(\"got invalid response on HTTP probe: %v\", rsp.StatusCode)\n\t}\n}\n\nfunc (e *enb) addIP(sub *Subscriber) error {\n\tlink, err := netlink.LinkByName(sub.EUuIFName)\n\tif err != nil {\n\t\treturn err\n\t}\n\taddrs, err := netlink.AddrList(link, netlink.FAMILY_ALL)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tnetToAdd := &net.IPNet{IP: net.ParseIP(sub.SrcIP), Mask: net.CIDRMask(24, 32)}\n\tvar addr netlink.Addr\n\tvar found bool\n\tfor _, a := range addrs {\n\t\tif a.Label == sub.EUuIFName {\n\t\t\tif a.IPNet.String() == netToAdd.String() {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\taddr = a\n\t\t\tfound = true\n\t\t}\n\t}\n\tif !found {\n\t\treturn fmt.Errorf(\"cannot find the interface to add address: %s\", sub.EUuIFName)\n\t}\n\n\taddr.IPNet = netToAdd\n\tif err := netlink.AddrAdd(link, &addr); err != nil {\n\t\treturn err\n\t}\n\n\te.mu.Lock()\n\tdefer e.mu.Unlock()\n\n\te.addedAddrs[link] = &addr\n\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/enb/enb.yml",
    "content": "mcc: \"001\"\nmnc: \"01\"\nrat_type: 6 # E-UTRAN\ntai: 0x0001\neci: 0x00000001\nlocal_addresses:\n  s1c_ip: \"127.0.1.11\"\n  s1u_ip: \"127.0.0.11\"\nmme_addr: \"127.0.1.12:36412\"\nuse_kernel_gtp: false\nprom_addr: \"127.0.10.1:58080\"\nsubscribers:\n  - imsi: \"001010000000001\"\n    msisdn: \"814000000001\"\n    imeisv: \"1234500000001\"\n    src_ip: \"192.168.101.201\"\n    i_tei: 1\n    type: \"http_get\"\n    euu_if_name: \"lo\"\n    http_url: \"http://172.16.0.102/\"\n    reattach_on_reload: false\n  - imsi: \"001010000000002\"\n    msisdn: \"814000000002\"\n    imeisv: \"1234500000002\"\n    src_ip: \"192.168.101.202\"\n    i_tei: 0\n    type: \"http_get\"\n    euu_if_name: \"lo\"\n    http_url: \"http://172.16.0.102/\"\n    reattach_on_reload: true\n  - imsi: \"001010000000003\"\n    msisdn: \"814000000003\"\n    imeisv: \"1234500000003\"\n    src_ip: \"192.168.101.203\"\n    i_tei: 0\n    type: \"http_get\"\n    euu_if_name: \"lo\"\n    http_url: \"http://172.16.0.102/\"\n    reattach_on_reload: false\n  - imsi: \"001010000000004\"\n    msisdn: \"814000000004\"\n    imeisv: \"1234500000004\"\n    src_ip: \"192.168.101.204\"\n    i_tei: 0\n    type: \"http_get\"\n    euu_if_name: \"lo\"\n    http_url: \"http://172.16.0.102/\"\n    reattach_on_reload: true\n  - imsi: \"001010000000005\"\n    msisdn: \"814000000005\"\n    imeisv: \"1234500000005\"\n    src_ip: \"192.168.101.205\"\n    i_tei: 0\n    type: \"http_get\"\n    euu_if_name: \"lo\"\n    http_url: \"http://172.16.0.102/\"\n    reattach_on_reload: false\n  # example for external client\n  #- imsi: \"001010000000006\"\n  #  msisdn: \"814000000006\"\n  #  imeisv: \"1234500000006\"\n  #  src_ip: \"192.168.101.101\"\n  #  i_tei: 1\n  #  type: \"external\"\n  #  euu_if_name: \"eth0\"\n  #  http_url: \"\"\n  #  reattach_on_reload: true\n"
  },
  {
    "path": "examples/gw-tester/enb/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command enb works as pseudo eNB that forwards packets through GTPv1 tunnel.\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n)\n\nfunc main() {\n\tvar configPath = flag.String(\"config\", \"./enb.yml\", \"Path to the configuration file.\")\n\tflag.Parse()\n\tlog.SetPrefix(\"[eNB] \")\n\n\tcfg, err := loadConfig(*configPath)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tenb, err := newENB(cfg)\n\tif err != nil {\n\t\tlog.Printf(\"failed to initialize eNB: %s\", err)\n\t}\n\tdefer enb.close()\n\n\tsigCh := make(chan os.Signal, 1)\n\tsignal.Notify(sigCh, syscall.SIGINT, syscall.SIGHUP)\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tfatalCh := make(chan error, 1)\n\tgo func() {\n\t\tif err := enb.run(ctx); err != nil {\n\t\t\tfatalCh <- err\n\t\t}\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase sig := <-sigCh:\n\t\t\tswitch sig {\n\t\t\tcase syscall.SIGINT:\n\t\t\t\treturn\n\t\t\tcase syscall.SIGHUP:\n\t\t\t\t// reload config and attach/detach subscribers again\n\t\t\t\tnewCfg, err := loadConfig(*configPath)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Printf(\"Error reloading config %s\", err)\n\t\t\t\t}\n\n\t\t\t\tif err := enb.reload(newCfg); err != nil {\n\t\t\t\t\tlog.Printf(\"Error applying reloaded config %s\", err)\n\t\t\t\t}\n\t\t\t}\n\t\tcase err := <-enb.errCh:\n\t\t\tlog.Printf(\"WARN: %s\", err)\n\t\tcase err := <-fatalCh:\n\t\t\tlog.Printf(\"FATAL: %s\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/gw-tester/enb/metrics.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"github.com/prometheus/client_golang/prometheus/promauto\"\n\t\"github.com/vishvananda/netlink\"\n)\n\ntype metricsCollector struct {\n\tactiveSessions   prometheus.GaugeFunc\n\tactiveBearers    prometheus.GaugeFunc\n\tmessagesSent     *prometheus.CounterVec\n\tmessagesReceived *prometheus.CounterVec\n}\n\nfunc (e *enb) runMetricsCollector() error {\n\tmc := &metricsCollector{}\n\tmc.activeSessions = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"enb_active_sessions\",\n\t\t\tHelp: \"number of session established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\treturn float64(len(e.sessions))\n\t\t},\n\t)\n\n\tmc.activeBearers = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"enb_active_bearers\",\n\t\t\tHelp: \"number of GTP-U tunnels established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\ttunnels, err := netlink.GTPPDPList()\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"metrics: could not get tunnels: %s\", err)\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn float64(len(tunnels))\n\t\t},\n\t)\n\n\tmc.messagesSent = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"enb_messages_sent_total\",\n\t\t\tHelp: \"number of message sent by messagge type\",\n\t\t},\n\t\t[]string{\"dst\", \"type\"},\n\t)\n\n\tmc.messagesReceived = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"enb_messages_received_total\",\n\t\t\tHelp: \"number of message received by messagge type\",\n\t\t},\n\t\t[]string{\"src\", \"type\"},\n\t)\n\n\te.mc = mc\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/mme/config.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"io/ioutil\"\n\n\t\"gopkg.in/yaml.v2\"\n)\n\n// Config is a configurations loaded from yaml.\ntype Config struct {\n\tLocalAddrs struct {\n\t\tS1CAddr string `yaml:\"s1c_addr\"`\n\t\tS11IP   string `yaml:\"s11_ip\"`\n\t} `yaml:\"local_addresses\"`\n\n\tPromAddr string `yaml:\"prom_addr\"`\n\n\tMCC string `yaml:\"mcc\"`\n\tMNC string `yaml:\"mnc\"`\n\n\tAPN string `yaml:\"apn\"`\n\n\tSgwS11 string `yaml:\"sgw_s11_ip\"`\n\tPgwS5C string `yaml:\"pgw_s5c_ip\"`\n}\n\nfunc loadConfig(path string) (*Config, error) {\n\tbuf, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tc := &Config{}\n\tif err := yaml.Unmarshal(buf, c); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n"
  },
  {
    "path": "examples/gw-tester/mme/handlers.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc (m *mme) handleCreateSessionResponse(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\tif m.mc != nil {\n\t\tm.mc.messagesReceived.WithLabelValues(sgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\t// find the session associated with TEID\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\tbearer := session.GetDefaultBearer()\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsRspFromSGW := msg.(*message.CreateSessionResponse)\n\n\t// check Cause value first.\n\tif causeIE := csRspFromSGW.Cause; causeIE != nil {\n\t\tcause, err := causeIE.Cause()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\tc.RemoveSession(session)\n\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\tMsgType: csRspFromSGW.MessageTypeName(),\n\t\t\t\tCause:   cause,\n\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", session.IMSI),\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: msg.MessageType()}\n\t}\n\n\tif paaIE := csRspFromSGW.PAA; paaIE != nil {\n\t\tbearer.SubscriberIP, err = paaIE.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif fteidcIE := csRspFromSGW.SenderFTEIDC; fteidcIE != nil {\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.AddTEID(gtpv2.IFTypeS11S4SGWGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\ts11sgwTEID, err := session.GetTEID(gtpv2.IFTypeS11S4SGWGTPC)\n\tif err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\ts11mmeTEID, err := session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\n\tif brCtxIE := csRspFromSGW.BearerContextsCreated; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.EPSBearerID:\n\t\t\t\tbearer.EBI, err = childIE.EPSBearerID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif childIE.Instance() != 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tit, err := childIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tteid, err := childIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, teid)\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tif err := session.Activate(); err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\n\tlog.Printf(\n\t\t\"Session created with S-GW for Subscriber: %s;\\n\\tS11 S-GW: %s, TEID->: %#x, TEID<-: %#x\",\n\t\tsession.Subscriber.IMSI, sgwAddr, s11sgwTEID, s11mmeTEID,\n\t)\n\tm.created <- struct{}{}\n\treturn nil\n}\n\nfunc (m *mme) handleModifyBearerResponse(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\tif m.mc != nil {\n\t\tm.mc.messagesReceived.WithLabelValues(sgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmbRspFromSGW := msg.(*message.ModifyBearerResponse)\n\tif causeIE := mbRspFromSGW.Cause; causeIE != nil {\n\t\tcause, err := causeIE.Cause()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\tMsgType: msg.MessageTypeName(),\n\t\t\t\tCause:   cause,\n\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", session.IMSI),\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.Cause}\n\t}\n\n\tif brCtxIE := mbRspFromSGW.BearerContextsModified; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif childIE.Instance() != 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tit, err := childIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tteid, err := childIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, teid)\n\n\t\t\t\tm.sgw.s1uIP, err = childIE.IPAddress()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tlog.Printf(\"Bearer modified with S-GW for Subscriber: %s\", session.IMSI)\n\tm.modified <- struct{}{}\n\treturn nil\n}\n\nfunc (m *mme) handleDeleteSessionResponse(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\tif m.mc != nil {\n\t\tm.mc.messagesReceived.WithLabelValues(sgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc.RemoveSession(session)\n\tlog.Printf(\"Session deleted with S-GW for Subscriber: %s\", session.IMSI)\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/mme/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command mme works as pseudo MME/HSS communicates S/P-GW with GTPv2 signaling.\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n)\n\nfunc main() {\n\tvar configPath = flag.String(\"config\", \"./mme.yml\", \"Path to the configuration file.\")\n\tflag.Parse()\n\tlog.SetPrefix(\"[MME] \")\n\n\tsigCh := make(chan os.Signal, 1)\n\tsignal.Notify(sigCh, syscall.SIGINT, syscall.SIGHUP)\n\n\tcfg, err := loadConfig(*configPath)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tmme, err := newMME(cfg)\n\tif err != nil {\n\t\tlog.Printf(\"failed to initialize MME: %s\", err)\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tfatalCh := make(chan error)\n\tgo func() {\n\t\tif err := mme.run(ctx); err != nil {\n\t\t\tfatalCh <- err\n\t\t}\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase sig := <-sigCh:\n\t\t\tswitch sig {\n\t\t\tcase syscall.SIGINT:\n\t\t\t\tcancel()\n\t\t\t\treturn\n\t\t\tcase syscall.SIGHUP:\n\t\t\t\t// reload config and attach/detach subscribers\n\t\t\t\tnewCfg, err := loadConfig(*configPath)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Printf(\"Error reloading config %s\", err)\n\t\t\t\t}\n\n\t\t\t\tif err := mme.reload(newCfg); err != nil {\n\t\t\t\t\tlog.Printf(\"Error applying reloaded config %s\", err)\n\t\t\t\t}\n\t\t\t}\n\t\tcase err := <-mme.errCh:\n\t\t\tlog.Printf(\"WARN: %s\", err)\n\t\tcase err := <-fatalCh:\n\t\t\tlog.Printf(\"FATAL: %s\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/gw-tester/mme/metrics.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"github.com/prometheus/client_golang/prometheus/promauto\"\n)\n\ntype metricsCollector struct {\n\tactiveSessions   prometheus.GaugeFunc\n\tmessagesSent     *prometheus.CounterVec\n\tmessagesReceived *prometheus.CounterVec\n}\n\nfunc (m *mme) runMetricsCollector() error {\n\tmc := &metricsCollector{}\n\tmc.activeSessions = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"mme_active_sessions\",\n\t\t\tHelp: \"number of session established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\treturn float64(m.s11Conn.SessionCount())\n\t\t},\n\t)\n\n\tmc.messagesSent = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"mme_messages_sent_total\",\n\t\t\tHelp: \"number of message sent by messagge type\",\n\t\t},\n\t\t[]string{\"dst\", \"type\"},\n\t)\n\n\tmc.messagesReceived = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"mme_messages_received_total\",\n\t\t\tHelp: \"number of message received by messagge type\",\n\t\t},\n\t\t[]string{\"src\", \"type\"},\n\t)\n\n\tm.mc = mc\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/mme/mme.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n\t\"google.golang.org/grpc\"\n\n\t\"github.com/wmnsk/go-gtp/examples/gw-tester/s1mme\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// Session represents a subscriber.\ntype Session struct {\n\tIMSI   string\n\tMSISDN string\n\tIMEISV string\n\n\tSrcIP string\n\n\titei uint32\n}\n\ntype mme struct {\n\ts1mmeListener net.Listener\n\ts11Addr       net.Addr\n\ts11IP         string\n\ts11Conn       *gtpv2.Conn\n\n\tcreated  chan struct{}\n\tmodified chan struct{}\n\n\tapn      string\n\tmcc, mnc string\n\n\tenb struct {\n\t\tmcc   string\n\t\tmnc   string\n\t\ttai   uint16\n\t\teci   uint32\n\t\ts1uIP string\n\t}\n\n\tsgw struct {\n\t\ts11IP string\n\t\ts1uIP string\n\t}\n\n\tpgw struct {\n\t\ts5cIP string\n\t}\n\n\tpromAddr string\n\tmc       *metricsCollector\n\n\terrCh chan error\n}\n\nfunc newMME(cfg *Config) (*mme, error) {\n\tm := &mme{\n\t\tmcc: cfg.MCC,\n\t\tmnc: cfg.MNC,\n\t\tapn: cfg.APN,\n\n\t\tcreated:  make(chan struct{}, 1),\n\t\tmodified: make(chan struct{}, 1),\n\n\t\terrCh: make(chan error, 1),\n\t}\n\tm.sgw.s11IP = cfg.SgwS11\n\tm.pgw.s5cIP = cfg.PgwS5C\n\n\t// setup S11 conn\n\tvar err error\n\tm.s11Addr, err = net.ResolveUDPAddr(\"udp\", cfg.LocalAddrs.S11IP+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm.s11IP = cfg.LocalAddrs.S11IP\n\n\t// setup gRPC server\n\tm.s1mmeListener, err = net.Listen(\"tcp\", cfg.LocalAddrs.S1CAddr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif cfg.PromAddr != \"\" {\n\t\t// validate if the address is valid or not.\n\t\tif _, err = net.ResolveTCPAddr(\"tcp\", cfg.PromAddr); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tm.promAddr = cfg.PromAddr\n\t}\n\n\treturn m, nil\n}\n\nfunc (m *mme) run(ctx context.Context) error {\n\tfatalCh := make(chan error, 1)\n\n\tsrv := grpc.NewServer()\n\ts1mme.RegisterAttacherServer(srv, m)\n\tgo func() {\n\t\tif err := srv.Serve(m.s1mmeListener); err != nil {\n\t\t\tfatalCh <- fmt.Errorf(\"error on serving gRPC: %w\", err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving S1-MME on: %s\", m.s1mmeListener.Addr())\n\n\tm.s11Conn = gtpv2.NewConn(m.s11Addr, gtpv2.IFTypeS11MMEGTPC, 0)\n\tgo func() {\n\t\tif err := m.s11Conn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving S11 on: %s\", m.s11Addr)\n\n\tm.s11Conn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionResponse: m.handleCreateSessionResponse,\n\t\tmessage.MsgTypeModifyBearerResponse:  m.handleModifyBearerResponse,\n\t\tmessage.MsgTypeDeleteSessionResponse: m.handleDeleteSessionResponse,\n\t})\n\n\t// start serving Prometheus, if address is given\n\tif m.promAddr != \"\" {\n\t\tif err := m.runMetricsCollector(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\thttp.Handle(\"/metrics\", promhttp.Handler())\n\t\tgo func() {\n\t\t\tif err := http.ListenAndServe(m.promAddr, nil); err != nil {\n\t\t\t\tlog.Println(err)\n\t\t\t}\n\t\t}()\n\t\tlog.Printf(\"Started serving Prometheus on %s\", m.promAddr)\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\t// srv.Serve returns when lis is closed\n\t\t\tif err := m.s1mmeListener.Close(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn nil\n\t\tcase err := <-fatalCh:\n\t\t\treturn err\n\t\t}\n\t}\n}\n\nfunc (m *mme) reload(cfg *Config) error {\n\t// TODO: implement\n\treturn nil\n}\n\n// Attach is called by eNB by gRPC.\nfunc (m *mme) Attach(ctx context.Context, req *s1mme.AttachRequest) (*s1mme.AttachResponse, error) {\n\tsess := &Session{\n\t\tIMSI:   req.Imsi,\n\t\tMSISDN: req.Msisdn,\n\t\tIMEISV: req.Imeisv,\n\t\tSrcIP:  req.SrcIp,\n\t\titei:   req.ITei,\n\t}\n\n\tvar err error\n\tm.enb.s1uIP, _, err = net.SplitHostPort(req.S1UAddr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terrCh := make(chan error, 1)\n\trspCh := make(chan *s1mme.AttachResponse)\n\tgo func() {\n\t\tm.enb.mcc = req.Location.Mcc\n\t\tm.enb.mnc = req.Location.Mnc\n\t\tm.enb.tai = uint16(req.Location.Tai)\n\t\tm.enb.eci = req.Location.Eci\n\n\t\tsession, err := m.CreateSession(sess)\n\t\tif err != nil {\n\t\t\terrCh <- err\n\t\t\treturn\n\t\t}\n\t\tlog.Printf(\"Sent Create Session Request for %s\", session.IMSI)\n\n\t\tselect {\n\t\tcase <-m.created:\n\t\t\t// go forward\n\t\tcase <-time.After(5 * time.Second):\n\t\t\terrCh <- fmt.Errorf(\"timed out: %s\", session.IMSI)\n\t\t}\n\n\t\tif _, err = m.ModifyBearer(session, sess); err != nil {\n\t\t\terrCh <- err\n\t\t\treturn\n\t\t}\n\t\tlog.Printf(\"Sent Modify Bearer Request for %s\", session.IMSI)\n\n\t\tselect {\n\t\tcase <-m.modified:\n\t\t\t// go forward\n\t\tcase <-time.After(5 * time.Second):\n\t\t\terrCh <- fmt.Errorf(\"timed out: %s\", session.IMSI)\n\t\t}\n\n\t\ts1teid, err := session.GetTEID(gtpv2.IFTypeS1USGWGTPU)\n\t\tif err != nil {\n\t\t\terrCh <- err\n\t\t\treturn\n\t\t}\n\n\t\trspCh <- &s1mme.AttachResponse{\n\t\t\tCause:   s1mme.Cause_SUCCESS,\n\t\t\tSgwAddr: m.sgw.s1uIP + gtpv2.GTPUPort,\n\t\t\tOTei:    s1teid,\n\t\t}\n\t}()\n\n\tselect {\n\tcase err := <-errCh:\n\t\treturn nil, err\n\tcase rsp := <-rspCh:\n\t\treturn rsp, nil\n\t}\n}\n\n// Detach is called by eNB by gRPC.\nfunc (m *mme) Detach(ctx context.Context, req *s1mme.DetachRequest) (*s1mme.DetachResponse, error) {\n\t// TODO: implement\n\treturn nil, nil\n}\n\nfunc (m *mme) CreateSession(sess *Session) (*gtpv2.Session, error) {\n\tbr := gtpv2.NewBearer(5, \"\", &gtpv2.QoSProfile{\n\t\tPL: 2, QCI: 255, MBRUL: 0xffffffff, MBRDL: 0xffffffff, GBRUL: 0xffffffff, GBRDL: 0xffffffff,\n\t})\n\tvar pci, pvi uint8\n\tif br.PCI {\n\t\tpci = 1\n\t}\n\tif br.PVI {\n\t\tpvi = 1\n\t}\n\n\traddr, err := net.ResolveUDPAddr(\"udp\", m.sgw.s11IP+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsession, _, err := m.s11Conn.CreateSession(\n\t\traddr,\n\t\tie.NewIMSI(sess.IMSI),\n\t\tie.NewMSISDN(sess.MSISDN),\n\t\tie.NewMobileEquipmentIdentity(sess.IMEISV),\n\t\tie.NewUserLocationInformationStruct(\n\t\t\tie.NewCGI(m.enb.mcc, m.enb.mnc, 0x1111, 0x2222),\n\t\t\tie.NewSAI(m.enb.mcc, m.enb.mnc, 0x1111, 0x3333),\n\t\t\tie.NewRAI(m.enb.mcc, m.enb.mnc, 0x1111, 0x4444),\n\t\t\tie.NewTAI(m.enb.mcc, m.enb.mnc, 0x5555),\n\t\t\tie.NewECGI(m.enb.mcc, m.enb.mnc, 0x66666666),\n\t\t\tie.NewLAI(m.enb.mcc, m.enb.mnc, 0x1111),\n\t\t\tie.NewMENBI(m.enb.mcc, m.enb.mnc, 0x11111111),\n\t\t\tie.NewEMENBI(m.enb.mcc, m.enb.mnc, 0x22222222),\n\t\t),\n\t\tie.NewRATType(gtpv2.RATTypeEUTRAN),\n\t\tie.NewIndicationFromOctets(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n\t\tm.s11Conn.NewSenderFTEID(m.s11IP, \"\"),\n\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPC, 0, m.pgw.s5cIP, \"\").WithInstance(1),\n\t\tie.NewAccessPointName(m.apn),\n\t\tie.NewSelectionMode(gtpv2.SelectionModeMSorNetworkProvidedAPNSubscribedVerified),\n\t\tie.NewPDNType(gtpv2.PDNTypeIPv4),\n\t\tie.NewPDNAddressAllocation(sess.SrcIP),\n\t\tie.NewAPNRestriction(gtpv2.APNRestrictionNoExistingContextsorRestriction),\n\t\tie.NewAggregateMaximumBitRate(0, 0),\n\t\tie.NewBearerContext(\n\t\t\tie.NewEPSBearerID(br.EBI),\n\t\t\tie.NewBearerQoS(pci, br.PL, pvi, br.QCI, br.MBRUL, br.MBRDL, br.GBRUL, br.GBRDL),\n\t\t),\n\t\tie.NewFullyQualifiedCSID(m.s11IP, 1),\n\t\tie.NewServingNetwork(m.mcc, m.mnc),\n\t\tie.NewUETimeZone(9*time.Hour, 0),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif m.mc != nil {\n\t\tm.mc.messagesSent.WithLabelValues(raddr.String(), \"Create Session Request\").Inc()\n\t}\n\n\treturn session, nil\n}\n\nfunc (m *mme) ModifyBearer(sess *gtpv2.Session, sub *Session) (*gtpv2.Bearer, error) {\n\tteid, err := sess.GetTEID(gtpv2.IFTypeS11S4SGWGTPC)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfteid := ie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, sub.itei, m.enb.s1uIP, \"\")\n\tif _, err = m.s11Conn.ModifyBearer(\n\t\tteid, sess, ie.NewIndicationFromOctets(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n\t\tie.NewBearerContext(ie.NewEPSBearerID(sess.GetDefaultBearer().EBI), fteid, ie.NewPortNumber(2125)),\n\t); err != nil {\n\t\treturn nil, err\n\t}\n\tif m.mc != nil {\n\t\tm.mc.messagesSent.WithLabelValues(sess.PeerAddr().String(), \"Modify Bearer Request\").Inc()\n\t}\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "examples/gw-tester/mme/mme.yml",
    "content": "mcc: \"001\"\nmnc: \"01\"\napn: \"gw-tester.go-gtp.example\"\nlocal_addresses:\n  s1c_addr: \"127.0.1.12:36412\"\n  s11_ip: \"127.0.1.12\"\nsgw_s11_ip: \"127.0.1.13\"\npgw_s5c_ip: \"127.0.1.15\"\nprom_addr: \"127.0.10.2:58080\"\n"
  },
  {
    "path": "examples/gw-tester/pgw/config.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"io/ioutil\"\n\n\t\"gopkg.in/yaml.v2\"\n)\n\n// Config is a configurations loaded from yaml.\ntype Config struct {\n\tLocalAddrs struct {\n\t\tS5CIP string `yaml:\"s5c_ip\"`\n\t\tS5UIP string `yaml:\"s5u_ip\"`\n\t\tSGiIP string `yaml:\"sgi_ip\"`\n\t} `yaml:\"local_addresses\"`\n\n\tUseKernelGTP bool `yaml:\"use_kernel_gtp\"`\n\n\tSGiIFName   string `yaml:\"sgi_if_name\"`\n\tRouteSubnet string `yaml:\"route_subnet\"`\n\n\tPromAddr string `yaml:\"prom_addr\"`\n}\n\nfunc loadConfig(path string) (*Config, error) {\n\tbuf, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tc := &Config{}\n\tif err := yaml.Unmarshal(buf, c); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n"
  },
  {
    "path": "examples/gw-tester/pgw/handlers.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc (p *pgw) handleCreateSessionRequest(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\tif p.mc != nil {\n\t\tp.mc.messagesReceived.WithLabelValues(sgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsReqFromSGW := msg.(*message.CreateSessionRequest)\n\n\t// keep session information retrieved from the message.\n\tsession := gtpv2.NewSession(sgwAddr, &gtpv2.Subscriber{Location: &gtpv2.Location{}})\n\tbearer := session.GetDefaultBearer()\n\tvar err error\n\tif imsiIE := csReqFromSGW.IMSI; imsiIE != nil {\n\t\timsi, err := imsiIE.IMSI()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.IMSI = imsi\n\n\t\t// remove previous session for the same subscriber if exists.\n\t\tsess, err := c.GetSessionByIMSI(imsi)\n\t\tif err != nil {\n\t\t\tswitch err.(type) {\n\t\t\tcase *gtpv2.UnknownIMSIError:\n\t\t\t\t// whole new session. just ignore.\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"got something unexpected: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\tc.RemoveSession(sess)\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.IMSI}\n\t}\n\tif msisdnIE := csReqFromSGW.MSISDN; msisdnIE != nil {\n\t\tsession.MSISDN, err = msisdnIE.MSISDN()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MSISDN}\n\t}\n\tif meiIE := csReqFromSGW.MEI; meiIE != nil {\n\t\tsession.IMEI, err = meiIE.MobileEquipmentIdentity()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MobileEquipmentIdentity}\n\t}\n\tif apnIE := csReqFromSGW.APN; apnIE != nil {\n\t\tbearer.APN, err = apnIE.AccessPointName()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.AccessPointName}\n\t}\n\tif netIE := csReqFromSGW.ServingNetwork; netIE != nil {\n\t\tsession.MCC, err = netIE.MCC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.MNC, err = netIE.MNC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.ServingNetwork}\n\t}\n\tif ratIE := csReqFromSGW.RATType; ratIE != nil {\n\t\tsession.RATType, err = ratIE.RATType()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.RATType}\n\t}\n\tif fteidcIE := csReqFromSGW.SenderFTEIDC; fteidcIE != nil {\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.AddTEID(gtpv2.IFTypeS5S8SGWGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\tvar s5sgwuIP string\n\tvar oteiU uint32\n\tif brCtxIE := csReqFromSGW.BearerContextsToBeCreated; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.EPSBearerID:\n\t\t\t\tbearer.EBI, err = childIE.EPSBearerID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tit, err := childIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\toteiU, err = childIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, oteiU)\n\n\t\t\t\ts5sgwuIP, err = childIE.IPAddress()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tif paaIE := csReqFromSGW.PAA; paaIE != nil {\n\t\tbearer.SubscriberIP, err = paaIE.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.PDNAddressAllocation}\n\t}\n\n\tcIP := strings.Split(c.LocalAddr().String(), \":\")[0]\n\tuIP := strings.Split(p.s5u, \":\")[0]\n\ts5cFTEID := c.NewSenderFTEID(cIP, \"\").WithInstance(1)\n\ts5uFTEID := p.uConn.NewFTEID(gtpv2.IFTypeS5S8PGWGTPU, uIP, \"\").WithInstance(2)\n\ts5sgwTEID, err := session.GetTEID(gtpv2.IFTypeS5S8SGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcsRspFromPGW := message.NewCreateSessionResponse(\n\t\ts5sgwTEID, 0,\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\ts5cFTEID,\n\t\tie.NewPDNAddressAllocation(bearer.SubscriberIP),\n\t\tie.NewAPNRestriction(gtpv2.APNRestrictionPublic2),\n\t\tie.NewBearerContext(\n\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\tie.NewEPSBearerID(bearer.EBI),\n\t\t\ts5uFTEID,\n\t\t\tie.NewChargingID(bearer.ChargingID),\n\t\t),\n\t)\n\tif csReqFromSGW.SGWFQCSID != nil {\n\t\tcsRspFromPGW.PGWFQCSID = ie.NewFullyQualifiedCSID(cIP, 1)\n\t}\n\tsession.AddTEID(gtpv2.IFTypeS5S8PGWGTPC, s5cFTEID.MustTEID())\n\tsession.AddTEID(gtpv2.IFTypeS5S8PGWGTPU, s5uFTEID.MustTEID())\n\n\tif err := c.RespondTo(sgwAddr, csReqFromSGW, csRspFromPGW); err != nil {\n\t\treturn err\n\t}\n\tif p.mc != nil {\n\t\tp.mc.messagesSent.WithLabelValues(sgwAddr.String(), csRspFromPGW.MessageTypeName()).Inc()\n\t}\n\n\ts5pgwTEID, err := session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// don't forget to activate and add session created to the session list\n\tif err := session.Activate(); err != nil {\n\t\treturn err\n\t}\n\tc.RegisterSession(s5pgwTEID, session)\n\n\tif p.useKernelGTP {\n\t\tif err := p.setupUPlane(net.ParseIP(s5sgwuIP), net.ParseIP(bearer.SubscriberIP), oteiU, s5uFTEID.MustTEID()); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tlog.Printf(\"Session created with S-GW for subscriber: %s;\\n\\tS5C S-GW: %s, TEID->: %#x, TEID<-: %#x\",\n\t\tsession.Subscriber.IMSI, sgwAddr, s5sgwTEID, s5pgwTEID,\n\t)\n\treturn nil\n}\n\nfunc (p *pgw) handleDeleteSessionRequest(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\tif p.mc != nil {\n\t\tp.mc.messagesReceived.WithLabelValues(sgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\tdsr := message.NewDeleteSessionResponse(\n\t\t\t0, 0,\n\t\t\tie.NewCause(gtpv2.CauseIMSIIMEINotKnown, 0, 0, 0, nil),\n\t\t)\n\t\tif err := c.RespondTo(sgwAddr, msg, dsr); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn err\n\t}\n\n\t// respond to S-GW with DeleteSessionResponse.\n\tteid, err := session.GetTEID(gtpv2.IFTypeS5S8SGWGTPC)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn nil\n\t}\n\tdsr := message.NewDeleteSessionResponse(\n\t\tteid, 0,\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t)\n\tif err := c.RespondTo(sgwAddr, msg, dsr); err != nil {\n\t\treturn err\n\t}\n\tif p.mc != nil {\n\t\tp.mc.messagesSent.WithLabelValues(sgwAddr.String(), dsr.MessageTypeName()).Inc()\n\t}\n\n\tlog.Printf(\"Session deleted for Subscriber: %s\", session.IMSI)\n\tc.RemoveSession(session)\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/pgw/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command pgw is a dead simple implementation of P-GW only with GTP-related features.\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n)\n\nfunc main() {\n\tvar configPath = flag.String(\"config\", \"./pgw.yml\", \"Path to the configuration file.\")\n\tflag.Parse()\n\tlog.SetPrefix(\"[P-GW] \")\n\n\tcfg, err := loadConfig(*configPath)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tpgw, err := newPGW(cfg)\n\tif err != nil {\n\t\tlog.Printf(\"failed to initialize P-GW: %s\", err)\n\t\treturn\n\t}\n\tdefer pgw.close()\n\n\tsigCh := make(chan os.Signal, 1)\n\tsignal.Notify(sigCh, syscall.SIGINT, syscall.SIGHUP)\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tfatalCh := make(chan error)\n\tgo func() {\n\t\tif err := pgw.run(ctx); err != nil {\n\t\t\tfatalCh <- err\n\t\t}\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase sig := <-sigCh:\n\t\t\t// TODO: reload config on receiving SIGHUP\n\t\t\tlog.Println(sig)\n\t\t\treturn\n\t\tcase err := <-pgw.errCh:\n\t\t\tlog.Printf(\"WARN: %s\", err)\n\t\tcase err := <-fatalCh:\n\t\t\tlog.Printf(\"FATAL: %s\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/gw-tester/pgw/metrics.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"github.com/prometheus/client_golang/prometheus/promauto\"\n\t\"github.com/vishvananda/netlink\"\n)\n\ntype metricsCollector struct {\n\tactiveSessions   prometheus.GaugeFunc\n\tactiveBearers    prometheus.GaugeFunc\n\tmessagesSent     *prometheus.CounterVec\n\tmessagesReceived *prometheus.CounterVec\n}\n\nfunc (p *pgw) runMetricsCollector() error {\n\tmc := &metricsCollector{}\n\tmc.activeSessions = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"pgw_active_sessions\",\n\t\t\tHelp: \"number of session established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\treturn float64(p.cConn.SessionCount())\n\t\t},\n\t)\n\n\tmc.activeBearers = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"pgw_active_bearers\",\n\t\t\tHelp: \"number of GTP-U tunnels established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\ttunnels, err := netlink.GTPPDPList()\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"metrics: could not get tunnels: %s\", err)\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn float64(len(tunnels))\n\t\t},\n\t)\n\n\tmc.messagesSent = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"pgw_messages_sent_total\",\n\t\t\tHelp: \"number of message sent by messagge type\",\n\t\t},\n\t\t[]string{\"dst\", \"type\"},\n\t)\n\n\tmc.messagesReceived = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"pgw_messages_received_total\",\n\t\t\tHelp: \"number of message received by messagge type\",\n\t\t},\n\t\t[]string{\"src\", \"type\"},\n\t)\n\n\tp.mc = mc\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/pgw/pgw.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n\t\"github.com/vishvananda/netlink\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\ntype pgw struct {\n\tcConn *gtpv2.Conn\n\tuConn *gtpv1.UPlaneConn\n\n\ts5c, s5u string\n\tsgiIF    string\n\n\tuseKernelGTP bool\n\n\trouteSubnet *net.IPNet\n\taddedRoutes []*netlink.Route\n\taddedRules  []*netlink.Rule\n\n\tpromAddr string\n\tmc       *metricsCollector\n\n\terrCh chan error\n}\n\nfunc newPGW(cfg *Config) (*pgw, error) {\n\tp := &pgw{\n\t\ts5c:          cfg.LocalAddrs.S5CIP + gtpv2.GTPCPort,\n\t\ts5u:          cfg.LocalAddrs.S5UIP + gtpv2.GTPUPort,\n\t\tuseKernelGTP: cfg.UseKernelGTP,\n\t\tsgiIF:        cfg.SGiIFName,\n\n\t\terrCh: make(chan error, 1),\n\t}\n\n\tvar err error\n\t_, p.routeSubnet, err = net.ParseCIDR(cfg.RouteSubnet)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif cfg.PromAddr != \"\" {\n\t\t// validate if the address is valid or not.\n\t\tif _, err = net.ResolveTCPAddr(\"tcp\", cfg.PromAddr); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tp.promAddr = cfg.PromAddr\n\t}\n\n\tif !p.useKernelGTP {\n\t\tlog.Println(\"WARN: U-Plane does not work without GTP kernel module\")\n\t}\n\n\treturn p, nil\n}\n\nfunc (p *pgw) run(ctx context.Context) error {\n\tcAddr, err := net.ResolveUDPAddr(\"udp\", p.s5c)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.cConn = gtpv2.NewConn(cAddr, gtpv2.IFTypeS5S8PGWGTPC, 0)\n\tgo func() {\n\t\tif err := p.cConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving S5-C on %s\", cAddr)\n\n\t// register handlers for ALL the message you expect remote endpoint to send.\n\tp.cConn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionRequest: p.handleCreateSessionRequest,\n\t\tmessage.MsgTypeDeleteSessionRequest: p.handleDeleteSessionRequest,\n\t})\n\n\tuAddr, err := net.ResolveUDPAddr(\"udp\", p.s5u)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.uConn = gtpv1.NewUPlaneConn(uAddr)\n\tif p.useKernelGTP {\n\t\tif err := p.uConn.EnableKernelGTP(\"gtp-pgw\", gtpv1.RoleGGSN); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tgo func() {\n\t\tif err = p.uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t\tlog.Println(\"uConn.ListenAndServe exitted\")\n\t}()\n\tlog.Printf(\"Started serving S5-U on %s\", uAddr)\n\n\t// start serving Prometheus, if address is given\n\tif p.promAddr != \"\" {\n\t\tif err := p.runMetricsCollector(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\thttp.Handle(\"/metrics\", promhttp.Handler())\n\t\tgo func() {\n\t\t\tif err := http.ListenAndServe(p.promAddr, nil); err != nil {\n\t\t\t\tlog.Println(err)\n\t\t\t}\n\t\t}()\n\t\tlog.Printf(\"Started serving Prometheus on %s\", p.promAddr)\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase err := <-p.errCh:\n\t\t\tlog.Printf(\"Warning: %s\", err)\n\t\t}\n\t}\n}\n\nfunc (p *pgw) close() error {\n\tvar errs []error\n\tfor _, r := range p.addedRoutes {\n\t\tif err := netlink.RouteDel(r); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\tfor _, r := range p.addedRules {\n\t\tif err := netlink.RuleDel(r); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif p.uConn != nil {\n\t\tif err := p.uConn.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif err := p.cConn.Close(); err != nil {\n\t\terrs = append(errs, err)\n\t}\n\n\tclose(p.errCh)\n\n\tif len(errs) > 0 {\n\t\treturn fmt.Errorf(\"errors while closing S-GW: %+v\", errs)\n\t}\n\treturn nil\n}\n\nfunc (p *pgw) setupUPlane(peerIP, msIP net.IP, otei, itei uint32) error {\n\tif err := p.uConn.AddTunnelOverride(peerIP, msIP, otei, itei); err != nil {\n\t\treturn err\n\t}\n\n\tms32 := &net.IPNet{IP: msIP, Mask: net.CIDRMask(32, 32)}\n\tdlroute := &netlink.Route{ // ip route replace\n\t\tDst:       ms32,                                 // UE's IP\n\t\tLinkIndex: p.uConn.KernelGTP.Link.Attrs().Index, // dev gtp-pgw\n\t\tScope:     netlink.SCOPE_LINK,                   // scope link\n\t\tProtocol:  4,                                    // proto static\n\t\tPriority:  1,                                    // metric 1\n\t\tTable:     3001,                                 // table 3001\n\t}\n\tif err := netlink.RouteReplace(dlroute); err != nil {\n\t\treturn err\n\t}\n\tp.addedRoutes = append(p.addedRoutes, dlroute)\n\n\tlink, err := netlink.LinkByName(p.sgiIF)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tulroute := &netlink.Route{ // ip route replace\n\t\tDst:       p.routeSubnet,      // dst network via SGi\n\t\tLinkIndex: link.Attrs().Index, // SGi I/F name\n\t\tScope:     netlink.SCOPE_LINK, // scope link\n\t\tProtocol:  4,                  // proto static\n\t\tPriority:  1,                  // metric 1\n\t}\n\tif err := netlink.RouteReplace(ulroute); err != nil {\n\t\treturn err\n\t}\n\tp.addedRoutes = append(p.addedRoutes, ulroute)\n\n\trules, err := netlink.RuleList(0)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, r := range rules {\n\t\tif r.IifName == link.Attrs().Name && r.Dst == ms32 {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\trule := netlink.NewRule()\n\trule.IifName = link.Attrs().Name\n\trule.Dst = ms32\n\trule.Table = 3001\n\tif err := netlink.RuleAdd(rule); err != nil {\n\t\treturn err\n\t}\n\tp.addedRules = append(p.addedRules, rule)\n\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/pgw/pgw.yml",
    "content": "local_addresses:\n  s5c_ip: \"127.0.1.15\"\n  s5u_ip: \"127.0.0.15\"\n  sgi_ip: \"127.0.1.254\"\nsgi_if_name: \"lo\"\nroute_subnet: \"192.168.101.0/24\"\nuse_kernel_gtp: false\nprom_addr: \"127.0.10.4:58080\"\n"
  },
  {
    "path": "examples/gw-tester/s1mme/s1mme.pb.go",
    "content": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// source: s1mme.proto\n\npackage s1mme\n\nimport (\n\tcontext \"context\"\n\tfmt \"fmt\"\n\tproto \"github.com/golang/protobuf/proto\"\n\tgrpc \"google.golang.org/grpc\"\n\tcodes \"google.golang.org/grpc/codes\"\n\tstatus \"google.golang.org/grpc/status\"\n\tmath \"math\"\n)\n\n// Reference imports to suppress errors if they are not otherwise used.\nvar _ = proto.Marshal\nvar _ = fmt.Errorf\nvar _ = math.Inf\n\n// This is a compile-time assertion to ensure that this generated file\n// is compatible with the proto package it is being compiled against.\n// A compilation error at this line likely means your copy of the\n// proto package needs to be updated.\nconst _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package\n\n// Cause represents a result of attach / detach.\ntype Cause int32\n\nconst (\n\tCause_INVALID        Cause = 0\n\tCause_SUCCESS        Cause = 1\n\tCause_GW_UNAVAILABLE Cause = 2\n)\n\nvar Cause_name = map[int32]string{\n\t0: \"INVALID\",\n\t1: \"SUCCESS\",\n\t2: \"GW_UNAVAILABLE\",\n}\n\nvar Cause_value = map[string]int32{\n\t\"INVALID\":        0,\n\t\"SUCCESS\":        1,\n\t\"GW_UNAVAILABLE\": 2,\n}\n\nfunc (x Cause) String() string {\n\treturn proto.EnumName(Cause_name, int32(x))\n}\n\nfunc (Cause) EnumDescriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{0}\n}\n\ntype Location_RATType int32\n\nconst (\n\tLocation_INVALID        Location_RATType = 0\n\tLocation_UTRAN          Location_RATType = 1\n\tLocation_GERAN          Location_RATType = 2\n\tLocation_WLAN           Location_RATType = 3\n\tLocation_GAN            Location_RATType = 4\n\tLocation_HSPA_EVOLUTION Location_RATType = 5\n\tLocation_EUTRAN         Location_RATType = 6\n\tLocation_VIRTUAL        Location_RATType = 7\n\tLocation_EUTRAN_NB_IOT  Location_RATType = 8\n\tLocation_LTEM           Location_RATType = 9\n\tLocation_NR             Location_RATType = 10\n)\n\nvar Location_RATType_name = map[int32]string{\n\t0:  \"INVALID\",\n\t1:  \"UTRAN\",\n\t2:  \"GERAN\",\n\t3:  \"WLAN\",\n\t4:  \"GAN\",\n\t5:  \"HSPA_EVOLUTION\",\n\t6:  \"EUTRAN\",\n\t7:  \"VIRTUAL\",\n\t8:  \"EUTRAN_NB_IOT\",\n\t9:  \"LTEM\",\n\t10: \"NR\",\n}\n\nvar Location_RATType_value = map[string]int32{\n\t\"INVALID\":        0,\n\t\"UTRAN\":          1,\n\t\"GERAN\":          2,\n\t\"WLAN\":           3,\n\t\"GAN\":            4,\n\t\"HSPA_EVOLUTION\": 5,\n\t\"EUTRAN\":         6,\n\t\"VIRTUAL\":        7,\n\t\"EUTRAN_NB_IOT\":  8,\n\t\"LTEM\":           9,\n\t\"NR\":             10,\n}\n\nfunc (x Location_RATType) String() string {\n\treturn proto.EnumName(Location_RATType_name, int32(x))\n}\n\nfunc (Location_RATType) EnumDescriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{2, 0}\n}\n\n// AttachRequest is used to request MME to create a session/bearer.\ntype AttachRequest struct {\n\tImsi                 string    `protobuf:\"bytes,1,opt,name=imsi,proto3\" json:\"imsi,omitempty\"`\n\tMsisdn               string    `protobuf:\"bytes,2,opt,name=msisdn,proto3\" json:\"msisdn,omitempty\"`\n\tImeisv               string    `protobuf:\"bytes,3,opt,name=imeisv,proto3\" json:\"imeisv,omitempty\"`\n\tS1UAddr              string    `protobuf:\"bytes,4,opt,name=s1u_addr,json=s1uAddr,proto3\" json:\"s1u_addr,omitempty\"`\n\tSrcIp                string    `protobuf:\"bytes,5,opt,name=src_ip,json=srcIp,proto3\" json:\"src_ip,omitempty\"`\n\tITei                 uint32    `protobuf:\"varint,6,opt,name=i_tei,json=iTei,proto3\" json:\"i_tei,omitempty\"`\n\tLocation             *Location `protobuf:\"bytes,7,opt,name=location,proto3\" json:\"location,omitempty\"`\n\tReattach             bool      `protobuf:\"varint,8,opt,name=reattach,proto3\" json:\"reattach,omitempty\"`\n\tXXX_NoUnkeyedLiteral struct{}  `json:\"-\"`\n\tXXX_unrecognized     []byte    `json:\"-\"`\n\tXXX_sizecache        int32     `json:\"-\"`\n}\n\nfunc (m *AttachRequest) Reset()         { *m = AttachRequest{} }\nfunc (m *AttachRequest) String() string { return proto.CompactTextString(m) }\nfunc (*AttachRequest) ProtoMessage()    {}\nfunc (*AttachRequest) Descriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{0}\n}\n\nfunc (m *AttachRequest) XXX_Unmarshal(b []byte) error {\n\treturn xxx_messageInfo_AttachRequest.Unmarshal(m, b)\n}\nfunc (m *AttachRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {\n\treturn xxx_messageInfo_AttachRequest.Marshal(b, m, deterministic)\n}\nfunc (m *AttachRequest) XXX_Merge(src proto.Message) {\n\txxx_messageInfo_AttachRequest.Merge(m, src)\n}\nfunc (m *AttachRequest) XXX_Size() int {\n\treturn xxx_messageInfo_AttachRequest.Size(m)\n}\nfunc (m *AttachRequest) XXX_DiscardUnknown() {\n\txxx_messageInfo_AttachRequest.DiscardUnknown(m)\n}\n\nvar xxx_messageInfo_AttachRequest proto.InternalMessageInfo\n\nfunc (m *AttachRequest) GetImsi() string {\n\tif m != nil {\n\t\treturn m.Imsi\n\t}\n\treturn \"\"\n}\n\nfunc (m *AttachRequest) GetMsisdn() string {\n\tif m != nil {\n\t\treturn m.Msisdn\n\t}\n\treturn \"\"\n}\n\nfunc (m *AttachRequest) GetImeisv() string {\n\tif m != nil {\n\t\treturn m.Imeisv\n\t}\n\treturn \"\"\n}\n\nfunc (m *AttachRequest) GetS1UAddr() string {\n\tif m != nil {\n\t\treturn m.S1UAddr\n\t}\n\treturn \"\"\n}\n\nfunc (m *AttachRequest) GetSrcIp() string {\n\tif m != nil {\n\t\treturn m.SrcIp\n\t}\n\treturn \"\"\n}\n\nfunc (m *AttachRequest) GetITei() uint32 {\n\tif m != nil {\n\t\treturn m.ITei\n\t}\n\treturn 0\n}\n\nfunc (m *AttachRequest) GetLocation() *Location {\n\tif m != nil {\n\t\treturn m.Location\n\t}\n\treturn nil\n}\n\nfunc (m *AttachRequest) GetReattach() bool {\n\tif m != nil {\n\t\treturn m.Reattach\n\t}\n\treturn false\n}\n\n// AttachResponse is used to respond to AttachRequest.\ntype AttachResponse struct {\n\tCause                Cause    `protobuf:\"varint,1,opt,name=cause,proto3,enum=s1mme.Cause\" json:\"cause,omitempty\"`\n\tSgwAddr              string   `protobuf:\"bytes,2,opt,name=sgw_addr,json=sgwAddr,proto3\" json:\"sgw_addr,omitempty\"`\n\tOTei                 uint32   `protobuf:\"varint,3,opt,name=o_tei,json=oTei,proto3\" json:\"o_tei,omitempty\"`\n\tXXX_NoUnkeyedLiteral struct{} `json:\"-\"`\n\tXXX_unrecognized     []byte   `json:\"-\"`\n\tXXX_sizecache        int32    `json:\"-\"`\n}\n\nfunc (m *AttachResponse) Reset()         { *m = AttachResponse{} }\nfunc (m *AttachResponse) String() string { return proto.CompactTextString(m) }\nfunc (*AttachResponse) ProtoMessage()    {}\nfunc (*AttachResponse) Descriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{1}\n}\n\nfunc (m *AttachResponse) XXX_Unmarshal(b []byte) error {\n\treturn xxx_messageInfo_AttachResponse.Unmarshal(m, b)\n}\nfunc (m *AttachResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {\n\treturn xxx_messageInfo_AttachResponse.Marshal(b, m, deterministic)\n}\nfunc (m *AttachResponse) XXX_Merge(src proto.Message) {\n\txxx_messageInfo_AttachResponse.Merge(m, src)\n}\nfunc (m *AttachResponse) XXX_Size() int {\n\treturn xxx_messageInfo_AttachResponse.Size(m)\n}\nfunc (m *AttachResponse) XXX_DiscardUnknown() {\n\txxx_messageInfo_AttachResponse.DiscardUnknown(m)\n}\n\nvar xxx_messageInfo_AttachResponse proto.InternalMessageInfo\n\nfunc (m *AttachResponse) GetCause() Cause {\n\tif m != nil {\n\t\treturn m.Cause\n\t}\n\treturn Cause_INVALID\n}\n\nfunc (m *AttachResponse) GetSgwAddr() string {\n\tif m != nil {\n\t\treturn m.SgwAddr\n\t}\n\treturn \"\"\n}\n\nfunc (m *AttachResponse) GetOTei() uint32 {\n\tif m != nil {\n\t\treturn m.OTei\n\t}\n\treturn 0\n}\n\n// Location represents a set of location-related information.\ntype Location struct {\n\tMcc                  string           `protobuf:\"bytes,1,opt,name=mcc,proto3\" json:\"mcc,omitempty\"`\n\tMnc                  string           `protobuf:\"bytes,2,opt,name=mnc,proto3\" json:\"mnc,omitempty\"`\n\tRatType              Location_RATType `protobuf:\"varint,3,opt,name=rat_type,json=ratType,proto3,enum=s1mme.Location_RATType\" json:\"rat_type,omitempty\"`\n\tTai                  uint32           `protobuf:\"varint,4,opt,name=tai,proto3\" json:\"tai,omitempty\"`\n\tEci                  uint32           `protobuf:\"varint,5,opt,name=eci,proto3\" json:\"eci,omitempty\"`\n\tXXX_NoUnkeyedLiteral struct{}         `json:\"-\"`\n\tXXX_unrecognized     []byte           `json:\"-\"`\n\tXXX_sizecache        int32            `json:\"-\"`\n}\n\nfunc (m *Location) Reset()         { *m = Location{} }\nfunc (m *Location) String() string { return proto.CompactTextString(m) }\nfunc (*Location) ProtoMessage()    {}\nfunc (*Location) Descriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{2}\n}\n\nfunc (m *Location) XXX_Unmarshal(b []byte) error {\n\treturn xxx_messageInfo_Location.Unmarshal(m, b)\n}\nfunc (m *Location) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {\n\treturn xxx_messageInfo_Location.Marshal(b, m, deterministic)\n}\nfunc (m *Location) XXX_Merge(src proto.Message) {\n\txxx_messageInfo_Location.Merge(m, src)\n}\nfunc (m *Location) XXX_Size() int {\n\treturn xxx_messageInfo_Location.Size(m)\n}\nfunc (m *Location) XXX_DiscardUnknown() {\n\txxx_messageInfo_Location.DiscardUnknown(m)\n}\n\nvar xxx_messageInfo_Location proto.InternalMessageInfo\n\nfunc (m *Location) GetMcc() string {\n\tif m != nil {\n\t\treturn m.Mcc\n\t}\n\treturn \"\"\n}\n\nfunc (m *Location) GetMnc() string {\n\tif m != nil {\n\t\treturn m.Mnc\n\t}\n\treturn \"\"\n}\n\nfunc (m *Location) GetRatType() Location_RATType {\n\tif m != nil {\n\t\treturn m.RatType\n\t}\n\treturn Location_INVALID\n}\n\nfunc (m *Location) GetTai() uint32 {\n\tif m != nil {\n\t\treturn m.Tai\n\t}\n\treturn 0\n}\n\nfunc (m *Location) GetEci() uint32 {\n\tif m != nil {\n\t\treturn m.Eci\n\t}\n\treturn 0\n}\n\n// DetachRequest is used to request MME to delete a session/bearer.\ntype DetachRequest struct {\n\tImsi                 string   `protobuf:\"bytes,1,opt,name=imsi,proto3\" json:\"imsi,omitempty\"`\n\tXXX_NoUnkeyedLiteral struct{} `json:\"-\"`\n\tXXX_unrecognized     []byte   `json:\"-\"`\n\tXXX_sizecache        int32    `json:\"-\"`\n}\n\nfunc (m *DetachRequest) Reset()         { *m = DetachRequest{} }\nfunc (m *DetachRequest) String() string { return proto.CompactTextString(m) }\nfunc (*DetachRequest) ProtoMessage()    {}\nfunc (*DetachRequest) Descriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{3}\n}\n\nfunc (m *DetachRequest) XXX_Unmarshal(b []byte) error {\n\treturn xxx_messageInfo_DetachRequest.Unmarshal(m, b)\n}\nfunc (m *DetachRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {\n\treturn xxx_messageInfo_DetachRequest.Marshal(b, m, deterministic)\n}\nfunc (m *DetachRequest) XXX_Merge(src proto.Message) {\n\txxx_messageInfo_DetachRequest.Merge(m, src)\n}\nfunc (m *DetachRequest) XXX_Size() int {\n\treturn xxx_messageInfo_DetachRequest.Size(m)\n}\nfunc (m *DetachRequest) XXX_DiscardUnknown() {\n\txxx_messageInfo_DetachRequest.DiscardUnknown(m)\n}\n\nvar xxx_messageInfo_DetachRequest proto.InternalMessageInfo\n\nfunc (m *DetachRequest) GetImsi() string {\n\tif m != nil {\n\t\treturn m.Imsi\n\t}\n\treturn \"\"\n}\n\n// DetachResponse is used to respond to DetachRequest.\ntype DetachResponse struct {\n\tCause                Cause    `protobuf:\"varint,1,opt,name=cause,proto3,enum=s1mme.Cause\" json:\"cause,omitempty\"`\n\tXXX_NoUnkeyedLiteral struct{} `json:\"-\"`\n\tXXX_unrecognized     []byte   `json:\"-\"`\n\tXXX_sizecache        int32    `json:\"-\"`\n}\n\nfunc (m *DetachResponse) Reset()         { *m = DetachResponse{} }\nfunc (m *DetachResponse) String() string { return proto.CompactTextString(m) }\nfunc (*DetachResponse) ProtoMessage()    {}\nfunc (*DetachResponse) Descriptor() ([]byte, []int) {\n\treturn fileDescriptor_24365dc18e89382c, []int{4}\n}\n\nfunc (m *DetachResponse) XXX_Unmarshal(b []byte) error {\n\treturn xxx_messageInfo_DetachResponse.Unmarshal(m, b)\n}\nfunc (m *DetachResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {\n\treturn xxx_messageInfo_DetachResponse.Marshal(b, m, deterministic)\n}\nfunc (m *DetachResponse) XXX_Merge(src proto.Message) {\n\txxx_messageInfo_DetachResponse.Merge(m, src)\n}\nfunc (m *DetachResponse) XXX_Size() int {\n\treturn xxx_messageInfo_DetachResponse.Size(m)\n}\nfunc (m *DetachResponse) XXX_DiscardUnknown() {\n\txxx_messageInfo_DetachResponse.DiscardUnknown(m)\n}\n\nvar xxx_messageInfo_DetachResponse proto.InternalMessageInfo\n\nfunc (m *DetachResponse) GetCause() Cause {\n\tif m != nil {\n\t\treturn m.Cause\n\t}\n\treturn Cause_INVALID\n}\n\nfunc init() {\n\tproto.RegisterEnum(\"s1mme.Cause\", Cause_name, Cause_value)\n\tproto.RegisterEnum(\"s1mme.Location_RATType\", Location_RATType_name, Location_RATType_value)\n\tproto.RegisterType((*AttachRequest)(nil), \"s1mme.AttachRequest\")\n\tproto.RegisterType((*AttachResponse)(nil), \"s1mme.AttachResponse\")\n\tproto.RegisterType((*Location)(nil), \"s1mme.Location\")\n\tproto.RegisterType((*DetachRequest)(nil), \"s1mme.DetachRequest\")\n\tproto.RegisterType((*DetachResponse)(nil), \"s1mme.DetachResponse\")\n}\n\nfunc init() { proto.RegisterFile(\"s1mme.proto\", fileDescriptor_24365dc18e89382c) }\n\nvar fileDescriptor_24365dc18e89382c = []byte{\n\t// 536 bytes of a gzipped FileDescriptorProto\n\t0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x4f, 0x6f, 0xd3, 0x4c,\n\t0x10, 0xc6, 0x6b, 0x27, 0xfe, 0xd3, 0xc9, 0xeb, 0xbc, 0xcb, 0x96, 0x82, 0xe9, 0x29, 0x32, 0x97,\n\t0x08, 0xa4, 0x4a, 0x0d, 0x20, 0xce, 0xdb, 0xd4, 0x0a, 0x96, 0x8c, 0x83, 0x36, 0x4e, 0x7a, 0xb4,\n\t0x8c, 0xbd, 0x2a, 0x2b, 0xe1, 0xd8, 0x78, 0x1d, 0xaa, 0x4a, 0x7c, 0x09, 0xae, 0x7c, 0x3d, 0xbe,\n\t0x08, 0xda, 0x5d, 0x27, 0x52, 0x7a, 0x81, 0xdb, 0x33, 0xcf, 0xec, 0x8c, 0xe7, 0x37, 0xde, 0x85,\n\t0x91, 0xb8, 0xaa, 0x2a, 0x76, 0xd9, 0xb4, 0x75, 0x57, 0x63, 0x4b, 0x05, 0xc1, 0x6f, 0x03, 0x3c,\n\t0xd2, 0x75, 0x79, 0xf1, 0x85, 0xb2, 0x6f, 0x3b, 0x26, 0x3a, 0x8c, 0x61, 0xc8, 0x2b, 0xc1, 0x7d,\n\t0x63, 0x62, 0x4c, 0x4f, 0xa9, 0xd2, 0xf8, 0x19, 0xd8, 0x95, 0xe0, 0xa2, 0xdc, 0xfa, 0xa6, 0x72,\n\t0xfb, 0x48, 0xfa, 0xbc, 0x62, 0x5c, 0x7c, 0xf7, 0x07, 0xda, 0xd7, 0x11, 0x7e, 0x01, 0xae, 0xb8,\n\t0xda, 0x65, 0x79, 0x59, 0xb6, 0xfe, 0x50, 0x65, 0x1c, 0x71, 0xb5, 0x23, 0x65, 0xd9, 0xe2, 0x73,\n\t0xb0, 0x45, 0x5b, 0x64, 0xbc, 0xf1, 0x2d, 0x95, 0xb0, 0x44, 0x5b, 0x44, 0x0d, 0x3e, 0x03, 0x8b,\n\t0x67, 0x1d, 0xe3, 0xbe, 0x3d, 0x31, 0xa6, 0x1e, 0x1d, 0xf2, 0x94, 0x71, 0xfc, 0x1a, 0xdc, 0xaf,\n\t0x75, 0x91, 0x77, 0xbc, 0xde, 0xfa, 0xce, 0xc4, 0x98, 0x8e, 0x66, 0xff, 0x5f, 0x6a, 0x86, 0xb8,\n\t0xb7, 0xe9, 0xe1, 0x00, 0xbe, 0x00, 0xb7, 0x65, 0xb9, 0x42, 0xf1, 0xdd, 0x89, 0x31, 0x75, 0xe9,\n\t0x21, 0x0e, 0x4a, 0x18, 0xef, 0x21, 0x45, 0x53, 0x6f, 0x05, 0xc3, 0x01, 0x58, 0x45, 0xbe, 0x13,\n\t0x4c, 0x61, 0x8e, 0x67, 0xff, 0xf5, 0x7d, 0xe7, 0xd2, 0xa3, 0x3a, 0xa5, 0x28, 0xee, 0xee, 0x35,\n\t0x85, 0xd9, 0x53, 0xdc, 0xdd, 0x2b, 0x8a, 0x33, 0xb0, 0x6a, 0x35, 0xee, 0x40, 0x8f, 0x5b, 0xa7,\n\t0x8c, 0x07, 0xbf, 0x4c, 0x70, 0xf7, 0x83, 0x61, 0x04, 0x83, 0xaa, 0x28, 0xfa, 0x2d, 0x4a, 0xa9,\n\t0x9c, 0x6d, 0xd1, 0x77, 0x92, 0x12, 0xcf, 0xc0, 0x6d, 0xf3, 0x2e, 0xeb, 0x1e, 0x1a, 0xa6, 0x1a,\n\t0x8d, 0x67, 0xcf, 0x1f, 0xf1, 0x5d, 0x52, 0x92, 0xa6, 0x0f, 0x0d, 0xa3, 0x4e, 0x9b, 0x77, 0x52,\n\t0xc8, 0x2e, 0x5d, 0xce, 0xd5, 0x56, 0x3d, 0x2a, 0xa5, 0x74, 0x58, 0xc1, 0xd5, 0x3a, 0x3d, 0x2a,\n\t0x65, 0xf0, 0xd3, 0x00, 0xa7, 0x2f, 0xc4, 0x23, 0x70, 0xa2, 0x64, 0x43, 0xe2, 0xe8, 0x06, 0x9d,\n\t0xe0, 0x53, 0xb0, 0xd6, 0x29, 0x25, 0x09, 0x32, 0xa4, 0x5c, 0x84, 0x52, 0x9a, 0xd8, 0x85, 0xe1,\n\t0x6d, 0x4c, 0x12, 0x34, 0xc0, 0x0e, 0x0c, 0x16, 0x24, 0x41, 0x43, 0x8c, 0x61, 0xfc, 0x61, 0xf5,\n\t0x89, 0x64, 0xe1, 0x66, 0x19, 0xaf, 0xd3, 0x68, 0x99, 0x20, 0x0b, 0x03, 0xd8, 0xa1, 0xae, 0xb6,\n\t0x65, 0xd7, 0x4d, 0x44, 0xd3, 0x35, 0x89, 0x91, 0x83, 0x9f, 0x80, 0xa7, 0x13, 0x59, 0x72, 0x9d,\n\t0x45, 0xcb, 0x14, 0xb9, 0xb2, 0x65, 0x9c, 0x86, 0x1f, 0xd1, 0x29, 0xb6, 0xc1, 0x4c, 0x28, 0x82,\n\t0xe0, 0x25, 0x78, 0x37, 0xec, 0x2f, 0xf7, 0x2c, 0x78, 0x0b, 0xe3, 0xfd, 0xa1, 0x7f, 0xff, 0x4f,\n\t0xaf, 0xde, 0x81, 0xa5, 0xe2, 0x63, 0xd6, 0x11, 0x38, 0xab, 0xf5, 0x7c, 0x1e, 0xae, 0x56, 0xc8,\n\t0x90, 0x3c, 0x8b, 0xdb, 0x6c, 0x9d, 0x90, 0x0d, 0x89, 0x62, 0x72, 0x1d, 0x87, 0xc8, 0x9c, 0xfd,\n\t0x00, 0x57, 0x5f, 0x0a, 0xd6, 0xe2, 0xf7, 0x60, 0x6b, 0x8d, 0x9f, 0xf6, 0x5f, 0x38, 0x7a, 0x14,\n\t0x17, 0xe7, 0x8f, 0x5c, 0x3d, 0x5d, 0x70, 0x22, 0x0b, 0xf5, 0xc4, 0x87, 0xc2, 0x23, 0xca, 0x43,\n\t0xe1, 0x31, 0x56, 0x70, 0xf2, 0xd9, 0x56, 0xcf, 0xf0, 0xcd, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff,\n\t0xf1, 0x17, 0x91, 0x66, 0x95, 0x03, 0x00, 0x00,\n}\n\n// Reference imports to suppress errors if they are not otherwise used.\nvar _ context.Context\nvar _ grpc.ClientConn\n\n// This is a compile-time assertion to ensure that this generated file\n// is compatible with the grpc package it is being compiled against.\nconst _ = grpc.SupportPackageIsVersion4\n\n// AttacherClient is the client API for Attacher service.\n//\n// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.\ntype AttacherClient interface {\n\tAttach(ctx context.Context, in *AttachRequest, opts ...grpc.CallOption) (*AttachResponse, error)\n\tDetach(ctx context.Context, in *DetachRequest, opts ...grpc.CallOption) (*DetachResponse, error)\n}\n\ntype attacherClient struct {\n\tcc *grpc.ClientConn\n}\n\nfunc NewAttacherClient(cc *grpc.ClientConn) AttacherClient {\n\treturn &attacherClient{cc}\n}\n\nfunc (c *attacherClient) Attach(ctx context.Context, in *AttachRequest, opts ...grpc.CallOption) (*AttachResponse, error) {\n\tout := new(AttachResponse)\n\terr := c.cc.Invoke(ctx, \"/s1mme.Attacher/Attach\", in, out, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc (c *attacherClient) Detach(ctx context.Context, in *DetachRequest, opts ...grpc.CallOption) (*DetachResponse, error) {\n\tout := new(DetachResponse)\n\terr := c.cc.Invoke(ctx, \"/s1mme.Attacher/Detach\", in, out, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// AttacherServer is the server API for Attacher service.\ntype AttacherServer interface {\n\tAttach(context.Context, *AttachRequest) (*AttachResponse, error)\n\tDetach(context.Context, *DetachRequest) (*DetachResponse, error)\n}\n\n// UnimplementedAttacherServer can be embedded to have forward compatible implementations.\ntype UnimplementedAttacherServer struct {\n}\n\nfunc (*UnimplementedAttacherServer) Attach(ctx context.Context, req *AttachRequest) (*AttachResponse, error) {\n\treturn nil, status.Errorf(codes.Unimplemented, \"method Attach not implemented\")\n}\nfunc (*UnimplementedAttacherServer) Detach(ctx context.Context, req *DetachRequest) (*DetachResponse, error) {\n\treturn nil, status.Errorf(codes.Unimplemented, \"method Detach not implemented\")\n}\n\nfunc RegisterAttacherServer(s *grpc.Server, srv AttacherServer) {\n\ts.RegisterService(&_Attacher_serviceDesc, srv)\n}\n\nfunc _Attacher_Attach_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(AttachRequest)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AttacherServer).Attach(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/s1mme.Attacher/Attach\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AttacherServer).Attach(ctx, req.(*AttachRequest))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nfunc _Attacher_Detach_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n\tin := new(DetachRequest)\n\tif err := dec(in); err != nil {\n\t\treturn nil, err\n\t}\n\tif interceptor == nil {\n\t\treturn srv.(AttacherServer).Detach(ctx, in)\n\t}\n\tinfo := &grpc.UnaryServerInfo{\n\t\tServer:     srv,\n\t\tFullMethod: \"/s1mme.Attacher/Detach\",\n\t}\n\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n\t\treturn srv.(AttacherServer).Detach(ctx, req.(*DetachRequest))\n\t}\n\treturn interceptor(ctx, in, info, handler)\n}\n\nvar _Attacher_serviceDesc = grpc.ServiceDesc{\n\tServiceName: \"s1mme.Attacher\",\n\tHandlerType: (*AttacherServer)(nil),\n\tMethods: []grpc.MethodDesc{\n\t\t{\n\t\t\tMethodName: \"Attach\",\n\t\t\tHandler:    _Attacher_Attach_Handler,\n\t\t},\n\t\t{\n\t\t\tMethodName: \"Detach\",\n\t\t\tHandler:    _Attacher_Detach_Handler,\n\t\t},\n\t},\n\tStreams:  []grpc.StreamDesc{},\n\tMetadata: \"s1mme.proto\",\n}\n"
  },
  {
    "path": "examples/gw-tester/s1mme/s1mme.proto",
    "content": "syntax = \"proto3\";\n\npackage s1mme;\n\n// Attacher defines the service to attach UE.\nservice Attacher {\n    rpc Attach (AttachRequest) returns (AttachResponse) {}\n    rpc Detach (DetachRequest) returns (DetachResponse) {}\n}\n\n// AttachRequest is used to request MME to create a session/bearer.\nmessage AttachRequest {\n    string imsi = 1;\n    string msisdn = 2;\n    string imeisv = 3;\n    string s1u_addr = 4;\n    string src_ip = 5;\n    uint32 i_tei = 6;\n    Location location = 7;\n    bool reattach = 8;\n}\n\n// AttachResponse is used to respond to AttachRequest.\nmessage AttachResponse {\n    Cause cause = 1; // result\n    string sgw_addr = 2;\n    uint32 o_tei = 3;\n}\n\n// Cause represents a result of attach / detach.\nenum Cause {\n    INVALID = 0;\n    SUCCESS = 1;\n    GW_UNAVAILABLE = 2;\n}\n\n// Location represents a set of location-related information.\nmessage Location {\n    string mcc = 1;\n    string mnc = 2;\n    RATType rat_type = 3;\n    uint32 tai = 4;\n    uint32 eci = 5;\n\n    enum RATType {\n        INVALID = 0;\n        UTRAN = 1;\n        GERAN = 2;\n        WLAN = 3;\n        GAN = 4;\n        HSPA_EVOLUTION = 5;\n        EUTRAN = 6;\n        VIRTUAL = 7;\n        EUTRAN_NB_IOT = 8;\n        LTEM = 9;\n        NR = 10;\n    }\n}\n\n// DetachRequest is used to request MME to delete a session/bearer.\nmessage DetachRequest {\n    string imsi = 1;\n}\n\n// DetachResponse is used to respond to DetachRequest.\nmessage DetachResponse {\n    Cause cause = 1;\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/config.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"io/ioutil\"\n\n\t\"gopkg.in/yaml.v2\"\n)\n\n// Config is a configurations loaded from yaml.\ntype Config struct {\n\tLocalAddrs struct {\n\t\tS11IP string `yaml:\"s11_ip\"`\n\t\tS1UIP string `yaml:\"s1u_ip\"`\n\t\tS5CIP string `yaml:\"s5c_ip\"`\n\t\tS5UIP string `yaml:\"s5u_ip\"`\n\t} `yaml:\"local_addresses\"`\n\n\tUseKernelGTP bool   `yaml:\"use_kernel_gtp\"`\n\tPromAddr     string `yaml:\"prom_addr\"`\n}\n\nfunc loadConfig(path string) (*Config, error) {\n\tbuf, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tc := &Config{}\n\tif err := yaml.Unmarshal(buf, c); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command sgw is a dead simple implementation of S-GW.\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n)\n\nfunc main() {\n\tvar configPath = flag.String(\"config\", \"./sgw.yml\", \"Path to the configuration file.\")\n\tflag.Parse()\n\tlog.SetPrefix(\"[S-GW] \")\n\n\tcfg, err := loadConfig(*configPath)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tsgw, err := newSGW(cfg)\n\tif err != nil {\n\t\tlog.Printf(\"failed to initialize SGW: %s\", err)\n\t}\n\tdefer sgw.close()\n\n\tsigCh := make(chan os.Signal, 1)\n\tsignal.Notify(sigCh, syscall.SIGINT, syscall.SIGHUP)\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tfatalCh := make(chan error)\n\tgo func() {\n\t\tif err := sgw.run(ctx); err != nil {\n\t\t\tfatalCh <- err\n\t\t}\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase sig := <-sigCh:\n\t\t\t// TODO: reload config on receiving SIGHUP\n\t\t\tlog.Println(sig)\n\t\t\treturn\n\t\tcase err := <-sgw.errCh:\n\t\t\tlog.Printf(\"WARN: %s\", err)\n\t\tcase err := <-fatalCh:\n\t\t\tlog.Printf(\"FATAL: %s\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/metrics.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"github.com/prometheus/client_golang/prometheus/promauto\"\n\t\"github.com/vishvananda/netlink\"\n)\n\ntype metricsCollector struct {\n\tactiveSessions   prometheus.GaugeFunc\n\tactiveBearers    prometheus.GaugeFunc\n\tmessagesSent     *prometheus.CounterVec\n\tmessagesReceived *prometheus.CounterVec\n}\n\nfunc (s *sgw) runMetricsCollector() error {\n\tmc := &metricsCollector{}\n\tmc.activeSessions = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"sgw_active_sessions\",\n\t\t\tHelp: \"number of session established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\treturn float64(s.s11Conn.SessionCount())\n\t\t},\n\t)\n\n\tmc.activeBearers = promauto.NewGaugeFunc(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"sgw_active_bearers\",\n\t\t\tHelp: \"number of GTP-U tunnels established currently\",\n\t\t},\n\t\tfunc() float64 {\n\t\t\ttunnels, err := netlink.GTPPDPList()\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"metrics: could not get tunnels: %s\", err)\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn float64(len(tunnels))\n\t\t},\n\t)\n\n\tmc.messagesSent = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"sgw_messages_sent_total\",\n\t\t\tHelp: \"number of message sent by messagge type\",\n\t\t},\n\t\t[]string{\"dst\", \"type\"},\n\t)\n\n\tmc.messagesReceived = promauto.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"sgw_messages_received_total\",\n\t\t\tHelp: \"number of message received by messagge type\",\n\t\t},\n\t\t[]string{\"src\", \"type\"},\n\t)\n\n\ts.mc = mc\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/s11_handlers.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc (s *sgw) handleCreateSessionRequest(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(mmeAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\ts11Session := gtpv2.NewSession(mmeAddr, &gtpv2.Subscriber{Location: &gtpv2.Location{}})\n\ts11Bearer := s11Session.GetDefaultBearer()\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsReqFromMME := msg.(*message.CreateSessionRequest)\n\n\tvar pgwAddrString string\n\tif fteidcIE := csReqFromMME.PGWS5S8FTEIDC; fteidcIE != nil {\n\t\tip, err := fteidcIE.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpgwAddrString = ip + gtpv2.GTPCPort\n\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts11Session.AddTEID(gtpv2.IFTypeS5S8PGWGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\tif fteidcIE := csReqFromMME.SenderFTEIDC; fteidcIE != nil {\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts11Session.AddTEID(gtpv2.IFTypeS11MMEGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\traddr, err := net.ResolveUDPAddr(\"udp\", pgwAddrString)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// keep session information retrieved from the message.\n\t// XXX - should return error if required IE is missing.\n\tif imsiIE := csReqFromMME.IMSI; imsiIE != nil {\n\t\timsi, err := imsiIE.IMSI()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// remove previous session for the same subscriber if exists.\n\t\tsess, err := s11Conn.GetSessionByIMSI(imsi)\n\t\tif err != nil {\n\t\t\tswitch err.(type) {\n\t\t\tcase *gtpv2.UnknownIMSIError:\n\t\t\t\t// whole new session. just ignore.\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"got something unexpected: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\ts11Conn.RemoveSession(sess)\n\t\t}\n\n\t\ts11Session.IMSI = imsi\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.IMSI}\n\t}\n\n\tif msisdnIE := csReqFromMME.MSISDN; msisdnIE != nil {\n\t\ts11Session.MSISDN, err = msisdnIE.MSISDN()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MSISDN}\n\t}\n\n\tif meiIE := csReqFromMME.MEI; meiIE != nil {\n\t\ts11Session.IMEI, err = meiIE.MobileEquipmentIdentity()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MobileEquipmentIdentity}\n\t}\n\n\tif apnIE := csReqFromMME.APN; apnIE != nil {\n\t\ts11Bearer.APN, err = apnIE.AccessPointName()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.AccessPointName}\n\t}\n\n\tif netIE := csReqFromMME.ServingNetwork; netIE != nil {\n\t\ts11Session.MCC, err = netIE.MCC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts11Session.MNC, err = netIE.MNC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.ServingNetwork}\n\t}\n\n\tif ratIE := csReqFromMME.RATType; ratIE != nil {\n\t\ts11Session.RATType, err = ratIE.RATType()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.RATType}\n\t}\n\ts11sgwFTEID := s11Conn.NewSenderFTEID(s.s11IP, \"\")\n\ts11sgwTEID := s11sgwFTEID.MustTEID()\n\ts11Conn.RegisterSession(s11sgwTEID, s11Session)\n\n\ts5cFTEID := s.s5cConn.NewSenderFTEID(s.s5cIP, \"\")\n\ts5uFTEID := s.s5uConn.NewFTEID(gtpv2.IFTypeS5S8SGWGTPU, s.s5uIP, \"\").WithInstance(2)\n\n\ts5Session, seq, err := s.s5cConn.CreateSession(\n\t\traddr,\n\t\tcsReqFromMME.IMSI, csReqFromMME.MSISDN, csReqFromMME.MEI, csReqFromMME.ServingNetwork,\n\t\tcsReqFromMME.RATType, csReqFromMME.IndicationFlags, s5cFTEID, csReqFromMME.PGWS5S8FTEIDC,\n\t\tcsReqFromMME.APN, csReqFromMME.SelectionMode, csReqFromMME.PDNType, csReqFromMME.PAA,\n\t\tcsReqFromMME.APNRestriction, csReqFromMME.AMBR, csReqFromMME.ULI,\n\t\tie.NewBearerContext(\n\t\t\tie.NewEPSBearerID(5),\n\t\t\ts5uFTEID,\n\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0, 0, 0, 0),\n\t\t),\n\t\tcsReqFromMME.MMEFQCSID,\n\t\tie.NewFullyQualifiedCSID(s.s5uIP, 1).WithInstance(1),\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5Session.AddTEID(s5uFTEID.MustInterfaceType(), s5uFTEID.MustTEID())\n\n\tlog.Printf(\"Sent Create Session Request to %s for %s\", pgwAddrString, s5Session.IMSI)\n\tif s.mc != nil {\n\t\ts.mc.messagesSent.WithLabelValues(mmeAddr.String(), \"Create Session Request\").Inc()\n\t}\n\n\tvar csRspFromSGW *message.CreateSessionResponse\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tincomingMsg, err := s11Session.WaitMessage(seq, 5*time.Second)\n\tif err != nil {\n\t\tcsRspFromSGW = message.NewCreateSessionResponse(\n\t\t\ts11mmeTEID, 0,\n\t\t\tie.NewCause(gtpv2.CauseNoResourcesAvailable, 0, 0, 0, nil),\n\t\t)\n\n\t\tif err := s11Conn.RespondTo(mmeAddr, csReqFromMME, csRspFromSGW); err != nil {\n\t\t\ts11Conn.RemoveSession(s11Session)\n\t\t\treturn err\n\t\t}\n\t\tlog.Printf(\n\t\t\t\"Sent %s with failure code: %d, target subscriber: %s\",\n\t\t\tcsRspFromSGW.MessageTypeName(), gtpv2.CausePGWNotResponding, s11Session.IMSI,\n\t\t)\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tvar csRspFromPGW *message.CreateSessionResponse\n\tswitch m := incomingMsg.(type) {\n\tcase *message.CreateSessionResponse:\n\t\t// move forward\n\t\tcsRspFromPGW = m\n\n\t\tbearer := s11Session.GetDefaultBearer()\n\t\tif ie := csRspFromPGW.PAA; ie != nil {\n\t\t\tbearer.SubscriberIP, err = ie.IPAddress()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\tdefault:\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn &gtpv2.UnexpectedTypeError{Msg: incomingMsg}\n\t}\n\n\t// if everything in CreateSessionResponse seems OK, relay it to MME.\n\ts1usgwFTEID := s.s1uConn.NewFTEID(gtpv2.IFTypeS1USGWGTPU, s.s1uIP, \"\")\n\tcsRspFromSGW = csRspFromPGW\n\tcsRspFromSGW.SenderFTEIDC = s11sgwFTEID\n\tcsRspFromSGW.SGWFQCSID = ie.NewFullyQualifiedCSID(s.s1uIP, 1).WithInstance(1)\n\tcsRspFromSGW.BearerContextsCreated[0].Add(s1usgwFTEID)\n\tcsRspFromSGW.BearerContextsCreated[0].Remove(ie.ChargingID, 0)\n\tcsRspFromSGW.SetTEID(s11mmeTEID)\n\tcsRspFromSGW.SetLength()\n\n\ts11Session.AddTEID(s11sgwFTEID.MustInterfaceType(), s11sgwTEID)\n\ts11Session.AddTEID(s1usgwFTEID.MustInterfaceType(), s1usgwFTEID.MustTEID())\n\n\tif err := s11Conn.RespondTo(mmeAddr, csReqFromMME, csRspFromSGW); err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\tif s.mc != nil {\n\t\ts.mc.messagesSent.WithLabelValues(mmeAddr.String(), csRspFromSGW.MessageTypeName()).Inc()\n\t}\n\n\ts5cpgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\ts5csgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8SGWGTPC)\n\tif err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tif err := s11Session.Activate(); err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tlog.Printf(\n\t\t\"Session created with MME and P-GW for Subscriber: %s;\\n\\tS11 MME:  %s, TEID->: %#x, TEID<-: %#x\\n\\tS5C P-GW: %s, TEID->: %#x, TEID<-: %#x\",\n\t\ts5Session.Subscriber.IMSI, mmeAddr, s11mmeTEID, s11sgwTEID, pgwAddrString, s5cpgwTEID, s5csgwTEID,\n\t)\n\treturn nil\n}\n\nfunc (s *sgw) handleModifyBearerRequest(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(mmeAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\ts11Session, err := s11Conn.GetSessionByTEID(msg.TEID(), mmeAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5cSession, err := s.s5cConn.GetSessionByIMSI(s11Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts1uBearer := s11Session.GetDefaultBearer()\n\ts5uBearer := s5cSession.GetDefaultBearer()\n\n\tvar enbIP string\n\tmbReqFromMME := msg.(*message.ModifyBearerRequest)\n\tif brCtxIE := mbReqFromMME.BearerContextsToBeModified; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.Indication:\n\t\t\t\t// do nothing in this implementation.\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif err := s.handleFTEIDU(childIE, s11Session, s1uBearer); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tenbIP, err = childIE.IPAddress()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts1usgwTEID, err := s11Session.GetTEID(gtpv2.IFTypeS1USGWGTPU)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5usgwTEID, err := s5cSession.GetTEID(gtpv2.IFTypeS5S8SGWGTPU)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpgwIP, _, err := net.SplitHostPort(s5uBearer.RemoteAddress().String())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif s.useKernelGTP {\n\t\tif err := s.s1uConn.AddTunnelOverride(\n\t\t\tnet.ParseIP(enbIP), net.ParseIP(s1uBearer.SubscriberIP), s1uBearer.OutgoingTEID(), s1usgwTEID,\n\t\t); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := s.s5uConn.AddTunnelOverride(\n\t\t\tnet.ParseIP(pgwIP), net.ParseIP(s5uBearer.SubscriberIP), s5uBearer.OutgoingTEID(), s5usgwTEID,\n\t\t); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif err := s.s1uConn.RelayTo(\n\t\t\ts.s5uConn, s1usgwTEID, s5uBearer.OutgoingTEID(), s5uBearer.RemoteAddress(),\n\t\t); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := s.s5uConn.RelayTo(\n\t\t\ts.s1uConn, s5usgwTEID, s1uBearer.OutgoingTEID(), s1uBearer.RemoteAddress(),\n\t\t); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tmbRspFromSGW := message.NewModifyBearerResponse(\n\t\ts11mmeTEID, 0,\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\tie.NewBearerContext(\n\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\tie.NewEPSBearerID(s1uBearer.EBI),\n\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, s1usgwTEID, s.s1uIP, \"\"),\n\t\t),\n\t)\n\n\tif err := s11Conn.RespondTo(mmeAddr, msg, mbRspFromSGW); err != nil {\n\t\treturn err\n\t}\n\tif s.mc != nil {\n\t\ts.mc.messagesSent.WithLabelValues(mmeAddr.String(), mbRspFromSGW.MessageTypeName()).Inc()\n\t}\n\n\tlog.Printf(\n\t\t\"Started listening on U-Plane for Subscriber: %s;\\n\\tS1-U: %s\\n\\tS5-U: %s\",\n\t\ts11Session.IMSI, s.s1uConn.LocalAddr(), s.s5uConn.LocalAddr(),\n\t)\n\treturn nil\n}\n\nfunc (s *sgw) handleDeleteSessionRequest(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(mmeAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tdsReqFromMME := msg.(*message.DeleteSessionRequest)\n\n\ts11Session, err := s11Conn.GetSessionByTEID(msg.TEID(), mmeAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5Session, err := s.s5cConn.GetSessionByIMSI(s11Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5cpgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tseq, err := s.s5cConn.DeleteSession(\n\t\ts5cpgwTEID, s5Session,\n\t\tie.NewEPSBearerID(s5Session.GetDefaultBearer().EBI),\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar dsRspFromSGW *message.DeleteSessionResponse\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tincomingMessage, err := s11Session.WaitMessage(seq, 5*time.Second)\n\tif err != nil {\n\t\tdsRspFromSGW = message.NewDeleteSessionResponse(\n\t\t\ts11mmeTEID, 0,\n\t\t\tie.NewCause(gtpv2.CausePGWNotResponding, 0, 0, 0, nil),\n\t\t)\n\n\t\tif err := s11Conn.RespondTo(mmeAddr, dsReqFromMME, dsRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlog.Printf(\n\t\t\t\"Sent %s with failure code: %d, target subscriber: %s\",\n\t\t\tdsRspFromSGW.MessageTypeName(), gtpv2.CausePGWNotResponding, s11Session.IMSI,\n\t\t)\n\t\tif s.mc != nil {\n\t\t\ts.mc.messagesSent.WithLabelValues(mmeAddr.String(), dsRspFromSGW.MessageTypeName()).Inc()\n\t\t}\n\t\treturn err\n\t}\n\n\t// use the cause as it is.\n\tswitch m := incomingMessage.(type) {\n\tcase *message.DeleteSessionResponse:\n\t\t// move forward\n\t\tdsRspFromSGW = m\n\tdefault:\n\t\treturn &gtpv2.UnexpectedTypeError{Msg: incomingMessage}\n\t}\n\n\tdsRspFromSGW.SetTEID(s11mmeTEID)\n\tif err := s11Conn.RespondTo(mmeAddr, msg, dsRspFromSGW); err != nil {\n\t\treturn err\n\t}\n\n\tlog.Printf(\"Session deleted for Subscriber: %s\", s11Session.IMSI)\n\tif s.mc != nil {\n\t\ts.mc.messagesSent.WithLabelValues(mmeAddr.String(), dsRspFromSGW.MessageTypeName()).Inc()\n\t}\n\n\ts11Conn.RemoveSession(s11Session)\n\treturn nil\n}\n\nfunc (s *sgw) handleDeleteBearerResponse(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(mmeAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\ts11Session, err := s11Conn.GetSessionByTEID(msg.TEID(), mmeAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5Session, err := s.s5cConn.GetSessionByIMSI(s11Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := gtpv2.PassMessageTo(s5Session, msg, 5*time.Second); err != nil {\n\t\treturn err\n\t}\n\n\t// remove bearer in handleDeleteBearerRequest instead of doing here,\n\t// as Delete Bearer Request does not necessarily have EBI.\n\treturn nil\n}\n\nfunc (s *sgw) handleFTEIDU(fteiduIE *ie.IE, session *gtpv2.Session, bearer *gtpv2.Bearer) error {\n\tif fteiduIE.Type != ie.FullyQualifiedTEID {\n\t\treturn &gtpv2.UnexpectedIEError{IEType: fteiduIE.Type}\n\t}\n\n\tip, err := fteiduIE.IPAddress()\n\tif err != nil {\n\t\treturn err\n\t}\n\taddr, err := net.ResolveUDPAddr(\"udp\", ip+gtpv2.GTPUPort)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbearer.SetRemoteAddress(addr)\n\n\tteid, err := fteiduIE.TEID()\n\tif err != nil {\n\t\treturn err\n\t}\n\tbearer.SetOutgoingTEID(teid)\n\n\tit, err := fteiduIE.InterfaceType()\n\tif err != nil {\n\t\treturn err\n\t}\n\tsession.AddTEID(it, teid)\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/s5_handlers.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc (s *sgw) handleCreateSessionResponse(s5cConn *gtpv2.Conn, pgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), pgwAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(pgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\ts5Session, err := s5cConn.GetSessionByTEID(msg.TEID(), pgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsRspFromPGW := msg.(*message.CreateSessionResponse)\n\n\t// check Cause value first.\n\tif causeIE := csRspFromPGW.Cause; causeIE != nil {\n\t\tcause, err := causeIE.Cause()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\ts5cConn.RemoveSession(s5Session)\n\t\t\t// this is not such a fatal error worth stopping the whole program.\n\t\t\t// in the real case it is better to take some action based on the Cause, though.\n\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\tMsgType: csRspFromPGW.MessageTypeName(),\n\t\t\t\tCause:   cause,\n\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", s5Session.IMSI),\n\t\t\t}\n\t\t}\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{\n\t\t\tType: ie.Cause,\n\t\t}\n\t}\n\n\tbearer := s5Session.GetDefaultBearer()\n\t// retrieve values that P-GW gave.\n\tif paaIE := csRspFromPGW.PAA; paaIE != nil {\n\t\tip, err := paaIE.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tbearer.SubscriberIP = ip\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.PDNAddressAllocation}\n\t}\n\n\tif fteidcIE := csRspFromPGW.PGWS5S8FTEIDC; fteidcIE != nil {\n\t\tit, err := fteidcIE.InterfaceType()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts5Session.AddTEID(it, teid)\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\tif brCtxIE := csRspFromPGW.BearerContextsCreated; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.Cause:\n\t\t\t\tcause, err := childIE.Cause()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\t\t\ts5cConn.RemoveSession(s5Session)\n\t\t\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\t\t\tMsgType: csRspFromPGW.MessageTypeName(),\n\t\t\t\t\t\tCause:   cause,\n\t\t\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", s5Session.IMSI),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase ie.EPSBearerID:\n\t\t\t\tebi, err := childIE.EPSBearerID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tbearer.EBI = ebi\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif err := s.handleFTEIDU(childIE, s5Session, bearer); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase ie.ChargingID:\n\t\t\t\tcid, err := childIE.ChargingID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tbearer.ChargingID = cid\n\t\t\t}\n\t\t}\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tif err := s5Session.Activate(); err != nil {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn err\n\t}\n\n\ts11Session, err := s.s11Conn.GetSessionByIMSI(s5Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := gtpv2.PassMessageTo(s11Session, csRspFromPGW, 5*time.Second); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (s *sgw) handleDeleteSessionResponse(s5cConn *gtpv2.Conn, pgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), pgwAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(pgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\ts5Session, err := s5cConn.GetSessionByTEID(msg.TEID(), pgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts11Session, err := s.s11Conn.GetSessionByIMSI(s5Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := gtpv2.PassMessageTo(s11Session, msg, 5*time.Second); err != nil {\n\t\treturn err\n\t}\n\n\t// even the cause indicates failure, session should be removed locally.\n\tlog.Printf(\"Session deleted for Subscriber: %s\", s5Session.IMSI)\n\ts5cConn.RemoveSession(s5Session)\n\treturn nil\n}\n\nfunc (s *sgw) handleDeleteBearerRequest(s5cConn *gtpv2.Conn, pgwAddr net.Addr, msg message.Message) error {\n\tlog.Printf(\"Received %s from %s\", msg.MessageTypeName(), pgwAddr)\n\tif s.mc != nil {\n\t\ts.mc.messagesReceived.WithLabelValues(pgwAddr.String(), msg.MessageTypeName()).Inc()\n\t}\n\n\ts5Session, err := s5cConn.GetSessionByTEID(msg.TEID(), pgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts11Session, err := s.s11Conn.GetSessionByIMSI(s5Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5cpgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tdbReqFromPGW := msg.(*message.DeleteBearerRequest)\n\n\tvar dbRspFromSGW *message.DeleteBearerResponse\n\tvar ebi *ie.IE\n\n\tif ie := dbReqFromPGW.LinkedEBI; ie != nil {\n\t\tebi = ie\n\t}\n\n\tif e := dbReqFromPGW.EBIs; e != nil {\n\t\tebiIE := e[0]\n\t\t// shouldn't be both.\n\t\tif ebi != nil {\n\t\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\t\ts5cpgwTEID, 0,\n\t\t\t\tie.NewCause(gtpv2.CauseContextNotFound, 0, 0, 0, ebiIE),\n\t\t\t)\n\t\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"%T from %s had both Linked EBI and EBIs IE\", dbReqFromPGW, pgwAddr)\n\t\t}\n\t\tebi = ebiIE\n\t}\n\n\tif ebi == nil {\n\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\ts5cpgwTEID, 0, ie.NewCause(gtpv2.CauseMandatoryIEMissing,\n\t\t\t\t0, 0, 0, ie.NewEPSBearerID(0),\n\t\t\t),\n\t\t)\n\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif s.mc != nil {\n\t\t\ts.mc.messagesSent.WithLabelValues(pgwAddr.String(), dbRspFromSGW.MessageTypeName()).Inc()\n\t\t}\n\t\treturn err\n\t}\n\n\t// check if bearer associated with EBI exists or not.\n\t_, err = s5Session.LookupBearerByEBI(ebi.MustEPSBearerID())\n\tif err != nil {\n\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\ts5cpgwTEID, 0,\n\t\t\tie.NewCause(gtpv2.CauseContextNotFound, 0, 0, 0, nil),\n\t\t)\n\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif s.mc != nil {\n\t\t\ts.mc.messagesSent.WithLabelValues(pgwAddr.String(), dbRspFromSGW.MessageTypeName()).Inc()\n\t\t}\n\t\treturn err\n\t}\n\n\t// forward to MME\n\tseq, err := s.s11Conn.DeleteBearer(s11mmeTEID, s11Session, ebi)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// wait for response from MME for 5 seconds\n\tincomingMessage, err := s5Session.WaitMessage(seq, 5*time.Second)\n\tif err != nil {\n\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\ts5cpgwTEID, 0,\n\t\t\tie.NewCause(gtpv2.CauseNoResourcesAvailable, 0, 0, 0, nil),\n\t\t)\n\n\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif s.mc != nil {\n\t\t\ts.mc.messagesSent.WithLabelValues(pgwAddr.String(), dbRspFromSGW.MessageTypeName()).Inc()\n\t\t}\n\n\t\t// remove anyway, as P-GW no longer keeps bearer locally\n\t\ts5Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\t\ts11Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\t\treturn err\n\t}\n\n\tswitch m := incomingMessage.(type) {\n\tcase *message.DeleteBearerResponse:\n\t\t// move forward\n\t\tdbRspFromSGW = m\n\tdefault:\n\t\treturn &gtpv2.UnexpectedTypeError{Msg: incomingMessage}\n\t}\n\n\tdbRspFromSGW.SetTEID(s5cpgwTEID)\n\tif err := s5cConn.RespondTo(pgwAddr, msg, dbRspFromSGW); err != nil {\n\t\treturn err\n\t}\n\tif s.mc != nil {\n\t\ts.mc.messagesSent.WithLabelValues(pgwAddr.String(), dbRspFromSGW.MessageTypeName()).Inc()\n\t}\n\n\ts5Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\ts11Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/sgw.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n\t\"github.com/vishvananda/netlink\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\ntype sgw struct {\n\t// C-Plane\n\ts11Addr, s5cAddr net.Addr\n\ts11Conn, s5cConn *gtpv2.Conn\n\n\t// U-Plane\n\ts1uAddr, s5uAddr net.Addr\n\ts1uConn, s5uConn *gtpv1.UPlaneConn\n\n\ts11IP, s5cIP, s1uIP, s5uIP string\n\n\tuseKernelGTP bool\n\n\taddedRoutes []*netlink.Route\n\taddedRules  []*netlink.Rule\n\n\tpromAddr string\n\tmc       *metricsCollector\n\n\terrCh chan error\n}\n\nfunc newSGW(cfg *Config) (*sgw, error) {\n\ts := &sgw{\n\t\terrCh: make(chan error, 1),\n\t}\n\n\tvar err error\n\ts.s11Addr, err = net.ResolveUDPAddr(\"udp\", cfg.LocalAddrs.S11IP+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.s11IP, _, err = net.SplitHostPort(s.s11Addr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ts.s5cAddr, err = net.ResolveUDPAddr(\"udp\", cfg.LocalAddrs.S5CIP+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.s5cIP, _, err = net.SplitHostPort(s.s5cAddr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ts.s1uAddr, err = net.ResolveUDPAddr(\"udp\", cfg.LocalAddrs.S1UIP+gtpv2.GTPUPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.s1uIP, _, err = net.SplitHostPort(s.s1uAddr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ts.s5uAddr, err = net.ResolveUDPAddr(\"udp\", cfg.LocalAddrs.S5UIP+gtpv2.GTPUPort)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts.s5uIP, _, err = net.SplitHostPort(s.s5uAddr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ts.useKernelGTP = cfg.UseKernelGTP\n\tif !s.useKernelGTP {\n\t\tlog.Println(\"WARN: U-Plane performance would be significantly less without Kernel GTP\")\n\t}\n\n\tif cfg.PromAddr != \"\" {\n\t\t// validate if the address is valid or not.\n\t\tif _, err = net.ResolveTCPAddr(\"tcp\", cfg.PromAddr); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ts.promAddr = cfg.PromAddr\n\t}\n\n\treturn s, nil\n}\n\nfunc (s *sgw) run(ctx context.Context) error {\n\ts.s11Conn = gtpv2.NewConn(s.s11Addr, gtpv2.IFTypeS11S4SGWGTPC, 0)\n\tgo func() {\n\t\tif err := s.s11Conn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving S11 on %s\", s.s11Addr)\n\n\ts.s5cConn = gtpv2.NewConn(s.s5cAddr, gtpv2.IFTypeS5S8SGWGTPC, 0)\n\tgo func() {\n\t\tif err := s.s5cConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving S5-C on %s\", s.s5cAddr)\n\n\t// register handlers for ALL the message you expect remote endpoint to send.\n\ts.s11Conn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionRequest: s.handleCreateSessionRequest,\n\t\tmessage.MsgTypeModifyBearerRequest:  s.handleModifyBearerRequest,\n\t\tmessage.MsgTypeDeleteSessionRequest: s.handleDeleteSessionRequest,\n\t\tmessage.MsgTypeDeleteBearerResponse: s.handleDeleteBearerResponse,\n\t})\n\ts.s5cConn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionResponse: s.handleCreateSessionResponse,\n\t\tmessage.MsgTypeDeleteSessionResponse: s.handleDeleteSessionResponse,\n\t\tmessage.MsgTypeDeleteBearerRequest:   s.handleDeleteBearerRequest,\n\t})\n\n\ts.s1uConn = gtpv1.NewUPlaneConn(s.s1uAddr)\n\tif s.useKernelGTP {\n\t\tif err := s.s1uConn.EnableKernelGTP(\"gtp-sgw-s1\", gtpv1.RoleGGSN); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tgo func() {\n\t\tif err := s.s1uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t\tlog.Println(\"uConn.ListenAndServe exitted\")\n\t}()\n\tlog.Printf(\"Started serving S1-U on %s\", s.s1uAddr)\n\n\ts.s5uConn = gtpv1.NewUPlaneConn(s.s5uAddr)\n\tif s.useKernelGTP {\n\t\tif err := s.s5uConn.EnableKernelGTP(\"gtp-sgw-s5\", gtpv1.RoleSGSN); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tgo func() {\n\t\tif err := s.s5uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t\tlog.Println(\"uConn.ListenAndServe exitted\")\n\t}()\n\tlog.Printf(\"Started serving S5-U on %s\", s.s5uAddr)\n\n\tif s.useKernelGTP {\n\t\tif err := s.addRoutes(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// start serving Prometheus, if address is given\n\tif s.promAddr != \"\" {\n\t\tif err := s.runMetricsCollector(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\thttp.Handle(\"/metrics\", promhttp.Handler())\n\t\tgo func() {\n\t\t\tif err := http.ListenAndServe(s.promAddr, nil); err != nil {\n\t\t\t\tlog.Println(err)\n\t\t\t}\n\t\t}()\n\t\tlog.Printf(\"Started serving Prometheus on %s\", s.promAddr)\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase err := <-s.errCh:\n\t\t\tlog.Printf(\"Warning: %+v\", err)\n\t\t}\n\t}\n}\n\nfunc (s *sgw) close() error {\n\tvar errs []error\n\tfor _, r := range s.addedRoutes {\n\t\tif err := netlink.RouteDel(r); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\tfor _, r := range s.addedRules {\n\t\tif err := netlink.RuleDel(r); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif s.s1uConn != nil {\n\t\tif err := s.s1uConn.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\tif s.s5uConn != nil {\n\t\tif err := s.s5uConn.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif s.s11Conn != nil {\n\t\tif err := s.s11Conn.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\tif s.s5cConn != nil {\n\t\tif err := s.s5cConn.Close(); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tclose(s.errCh)\n\n\tif len(errs) > 0 {\n\t\treturn fmt.Errorf(\"errors while closing S-GW: %+v\", errs)\n\t}\n\treturn nil\n}\n\nfunc (s *sgw) addRoutes() error {\n\tdefnet := &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)}\n\ts1route := &netlink.Route{ // ip route replace\n\t\tDst:       defnet,                         // default\n\t\tLinkIndex: s.s5uConn.KernelGTP.Link.Index, // dev gtp-s5\n\t\tScope:     netlink.SCOPE_LINK,             // scope link\n\t\tProtocol:  4,                              // proto static\n\t\tPriority:  1,                              // metric 1\n\t\tTable:     2001,                           // table 2001\n\t}\n\n\tif err := netlink.RouteReplace(s1route); err != nil {\n\t\treturn err\n\t}\n\ts.addedRoutes = append(s.addedRoutes, s1route)\n\n\ts5route := &netlink.Route{ // ip route replace\n\t\tDst:       defnet,                                 // default\n\t\tLinkIndex: s.s1uConn.KernelGTP.Link.Attrs().Index, // dev gtp-s1\n\t\tScope:     netlink.SCOPE_LINK,                     // scope link\n\t\tProtocol:  4,                                      // proto static\n\t\tPriority:  1,                                      // metric 1\n\t\tTable:     2005,                                   // table 2005\n\t}\n\n\tif err := netlink.RouteReplace(s5route); err != nil {\n\t\treturn err\n\t}\n\ts.addedRoutes = append(s.addedRoutes, s1route)\n\n\trules, err := netlink.RuleList(0)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar s1found, s5found bool\n\tfor _, r := range rules {\n\t\tif s1found && s5found {\n\t\t\tbreak\n\t\t}\n\n\t\tif r.IifName == s.s1uConn.KernelGTP.Link.Name && r.Table == 2001 {\n\t\t\ts1found = true\n\t\t}\n\t\tif r.IifName == s.s5uConn.KernelGTP.Link.Name && r.Table == 2005 {\n\t\t\ts5found = true\n\t\t}\n\t}\n\n\tif !s1found {\n\t\trule := netlink.NewRule()\n\t\trule.IifName = s.s1uConn.KernelGTP.Link.Name\n\t\trule.Table = 2001\n\n\t\tif err := netlink.RuleAdd(rule); err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts.addedRules = append(s.addedRules, rule)\n\t}\n\n\tif !s5found {\n\t\trule := netlink.NewRule()\n\t\trule.IifName = s.s5uConn.KernelGTP.Link.Name\n\t\trule.Table = 2005\n\n\t\tif err := netlink.RuleAdd(rule); err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts.addedRules = append(s.addedRules, rule)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "examples/gw-tester/sgw/sgw.yml",
    "content": "local_addresses:\n  s11_ip: \"127.0.1.13\"\n  s1u_ip: \"127.0.0.13\"\n  s5c_ip: \"127.0.1.14\"\n  s5u_ip: \"127.0.0.14\"\nuse_kernel_gtp: false\nprom_addr: \"127.0.10.3:58080\"\n"
  },
  {
    "path": "examples/mme/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command mme is a reference implementation of MME with go-gtp.\n//\n// MME follows the steps below if there's no unexpected events in the middle.\n// Note that the  S1 and DNS procedures is just mocked to make it work in\n// standalone manner.\n//\n// 1. Exchange Echo to S-GW address specified in command-line argument.\n//\n// 2. Start dispatching subscribers by sending Create Session Request to S-GW.\n// APN is handled with getPGWIP(), which is hard-coded.\n//\n// 3. Wait for Create Session Response coming from S-GW with Cause=\"request accepted\".\n//\n// 4. Create mocked UE and eNB with the required values set as told by S-GW, start\n// listening on the interface specified with s1enb flag,  and send Modify Bearer Request\n// to S-GW.\n//\n// 5. Wait for Modify Bearer Response coming from S-GW with Cause=\"request accepted\".\n//\n// 6. Start sending payload(ICMP Echo Request) encapsulated with GTPv1-U Header, and printing\n// the payload of encapsulated packets received.\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// command-line flags.\nvar (\n\ts11mme = flag.String(\"s11mme\", \"127.0.0.111\", \"local IP on S11 interface.\")\n\ts11sgw = flag.String(\"s11sgw\", \"127.0.0.112\", \"S-GW's IP on S11 interface.\")\n\ts1enb  = flag.String(\"s1enb\", \"127.0.0.1\", \"local IP on S1-U of pseudo eNB.\")\n)\n\n// variables globally shared.\nvar (\n\tattachCh  = make(chan *gtpv2.Subscriber)\n\tcreatedCh = make(chan string)\n\tloggerCh  = make(chan string)\n\terrCh     = make(chan error)\n\n\tonce  = sync.Once{}\n\tdelWG = sync.WaitGroup{}\n)\n\nfunc main() {\n\tflag.Parse()\n\tlog.SetPrefix(\"[MME] \")\n\n\tladdr, err := net.ResolveUDPAddr(\"udp\", *s11mme+gtpv2.GTPCPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\traddr, err := net.ResolveUDPAddr(\"udp\", *s11sgw+gtpv2.GTPCPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\t// setup *Conn first to check if the remote endpoint is awaken.\n\ts11Conn, err := gtpv2.Dial(ctx, laddr, raddr, gtpv2.IFTypeS11MMEGTPC, 0)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\tdefer s11Conn.Close()\n\tlog.Printf(\"Connection established with %s\", raddr.String())\n\n\t// register handlers for ALL the message you expect remote endpoint to send.\n\t// by default, Echo and VersionNotsupported is handled without explicit declaration.\n\ts11Conn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionResponse: handleCreateSessionResponse,\n\t\tmessage.MsgTypeModifyBearerResponse:  handleModifyBearerResponse,\n\t\tmessage.MsgTypeDeleteSessionResponse: handleDeleteSessionResponse,\n\t})\n\n\t// Listen on eNB S1-U interface.\n\tenbUPlaneAddr, err := net.ResolveUDPAddr(\"udp\", *s1enb+gtpv2.GTPUPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tuConn = gtpv1.NewUPlaneConn(enbUPlaneAddr)\n\tdefer uConn.Close()\n\n\tgo func() {\n\t\tif err = uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started listening on %s\", enbUPlaneAddr)\n\n\t// here you should wait for UEs to come attaching to your network.\n\t// in this example, the following five subscribers are to be attached.\n\t// working as worker-dispatcher is preferable in the real case\n\tgo dispatch([]*gtpv2.Subscriber{{\n\t\tIMSI: \"123451234567891\", MSISDN: \"8130900000001\", IMEI: \"123456780000011\",\n\t\tLocation: &gtpv2.Location{MCC: \"123\", MNC: \"45\", RATType: gtpv2.RATTypeEUTRAN, TAI: 0x0001, ECI: 0x00000101},\n\t}, {\n\t\tIMSI: \"123451234567892\", MSISDN: \"8130900000002\", IMEI: \"123456780000012\",\n\t\tLocation: &gtpv2.Location{MCC: \"123\", MNC: \"45\", RATType: gtpv2.RATTypeEUTRAN, TAI: 0x0002, ECI: 0x00000202},\n\t}, {\n\t\tIMSI: \"123451234567893\", MSISDN: \"8130900000003\", IMEI: \"123456780000013\",\n\t\tLocation: &gtpv2.Location{MCC: \"123\", MNC: \"45\", RATType: gtpv2.RATTypeEUTRAN, TAI: 0x0003, ECI: 0x00000303},\n\t}, {\n\t\tIMSI: \"123451234567894\", MSISDN: \"8130900000004\", IMEI: \"123456780000014\",\n\t\tLocation: &gtpv2.Location{MCC: \"123\", MNC: \"45\", RATType: gtpv2.RATTypeEUTRAN, TAI: 0x0004, ECI: 0x00000404},\n\t}, {\n\t\tIMSI: \"123451234567895\", MSISDN: \"8130900000005\", IMEI: \"123456780000015\",\n\t\tLocation: &gtpv2.Location{MCC: \"123\", MNC: \"45\", RATType: gtpv2.RATTypeEUTRAN, TAI: 0x0005, ECI: 0x00000505},\n\t}})\n\n\tbearer := gtpv2.NewBearer(5, \"\", &gtpv2.QoSProfile{\n\t\tPL: 2, QCI: 255, MBRUL: 0xffffffff, MBRDL: 0xffffffff, GBRUL: 0xffffffff, GBRDL: 0xffffffff,\n\t})\n\tfor {\n\t\tselect {\n\t\t// print logs coming from handlers working background\n\t\tcase str := <-loggerCh:\n\t\t\tlog.Println(str)\n\t\t// print errors coming from handlers working background\n\t\t// it's better to switch over the error to distinguish fatal ones to others.\n\t\tcase err := <-errCh:\n\t\t\tlog.Printf(\"Warning: %s\", err)\n\t\t// handle attach requests\n\t\tcase sub := <-attachCh:\n\t\t\tlog.Printf(\"Started creating session for subscriber: %s\", sub.IMSI)\n\t\t\tgo func() {\n\t\t\t\tbearer.APN = \"some-apn-1.example\"\n\t\t\t\tif sub.TAI%2 == 0 {\n\t\t\t\t\tbearer.APN = \"some-apn-2.example\"\n\t\t\t\t}\n\t\t\t\tif err := handleAttach(raddr, s11Conn, sub, bearer); err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}()\n\t\tcase imsi := <-createdCh:\n\t\t\tgo func() {\n\t\t\t\tsess, err := s11Conn.GetSessionByIMSI(imsi)\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tenbIP := strings.Split(*s1enb, \":\")[0]\n\t\t\t\tenbFTEID := uConn.NewFTEID(gtpv2.IFTypeS1UeNodeBGTPU, enbIP, \"\")\n\t\t\t\tteid, err := sess.GetTEID(gtpv2.IFTypeS11S4SGWGTPC)\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t}\n\n\t\t\t\tif _, err := s11Conn.ModifyBearer(\n\t\t\t\t\tteid, sess,\n\t\t\t\t\tie.NewIndicationFromOctets(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n\t\t\t\t\tie.NewBearerContext(ie.NewEPSBearerID(sess.GetDefaultBearer().EBI), enbFTEID),\n\t\t\t\t); err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tit, err := enbFTEID.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tenbTEID, err := enbFTEID.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tsess.AddTEID(it, enbTEID)\n\n\t\t\t\tloggerCh <- fmt.Sprintf(\"Sent Modify Bearer Request for %s\", imsi)\n\t\t\t}()\n\t\t// delete all the sessions after 30 seconds\n\t\tcase <-time.After(30 * time.Second):\n\t\t\tfor _, sess := range s11Conn.Sessions() {\n\t\t\t\tteid, err := sess.GetTEID(gtpv2.IFTypeS11S4SGWGTPC)\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- gtpv2.ErrTEIDNotFound\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif _, err := s11Conn.DeleteSession(teid, sess); err != nil {\n\t\t\t\t\tlog.Printf(\"Warning: %s\", err)\n\t\t\t\t}\n\t\t\t\tdelWG.Add(1)\n\t\t\t\tlog.Printf(\"Sent Delete Session Request for %s\", sess.IMSI)\n\t\t\t}\n\n\t\t\t// invoke goroutine to let the logger work\n\t\t\tgo func() {\n\t\t\t\tdelWG.Wait()\n\t\t\t\tlog.Fatal(\"Inactivity timer expired, exitting...\")\n\t\t\t}()\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/mme/mme.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc handleCreateSessionResponse(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tloggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\n\t// find the session associated with TEID\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\tbearer := session.GetDefaultBearer()\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsRspFromSGW := msg.(*message.CreateSessionResponse)\n\n\t// check Cause value first.\n\tif ie := csRspFromSGW.Cause; ie != nil {\n\t\tcause, err := ie.Cause()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\tc.RemoveSession(session)\n\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\tMsgType: csRspFromSGW.MessageTypeName(),\n\t\t\t\tCause:   cause,\n\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", session.IMSI),\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: msg.MessageType()}\n\t}\n\n\tif ie := csRspFromSGW.PAA; ie != nil {\n\t\tbearer.SubscriberIP, err = ie.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif senderIE := csRspFromSGW.SenderFTEIDC; senderIE != nil {\n\t\tteid, err := senderIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.AddTEID(gtpv2.IFTypeS11S4SGWGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\ts11sgwTEID, err := session.GetTEID(gtpv2.IFTypeS11S4SGWGTPC)\n\tif err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\ts11mmeTEID, err := session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\n\tif brCtxIE := csRspFromSGW.BearerContextsCreated; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.EPSBearerID:\n\t\t\t\tbearer.EBI, err = childIE.EPSBearerID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif childIE.Instance() != 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tit, err := childIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tteid, err := childIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, teid)\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tif err := session.Activate(); err != nil {\n\t\tc.RemoveSession(session)\n\t\treturn err\n\t}\n\n\tcreatedCh <- session.Subscriber.IMSI\n\tloggerCh <- fmt.Sprintf(\n\t\t\"Session created with S-GW for Subscriber: %s;\\n\\tS11 S-GW: %s, TEID->: %#x, TEID<-: %#x\",\n\t\tsession.Subscriber.IMSI, sgwAddr, s11sgwTEID, s11mmeTEID,\n\t)\n\treturn nil\n}\n\nfunc handleModifyBearerResponse(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tloggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmbRspFromSGW := msg.(*message.ModifyBearerResponse)\n\tif causeIE := mbRspFromSGW.Cause; causeIE != nil {\n\t\tcause, err := causeIE.Cause()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\tMsgType: msg.MessageTypeName(),\n\t\t\t\tCause:   cause,\n\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", session.IMSI),\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.Cause}\n\t}\n\n\tmock := &mockUEeNB{\n\t\tsubscriberIP: session.GetDefaultBearer().SubscriberIP,\n\t\tpayload:      payload,\n\t}\n\tif brCtxIE := mbRspFromSGW.BearerContextsModified; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif childIE.Instance() != 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tit, err := childIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tteid, err := childIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, teid)\n\n\t\t\t\tip, err := childIE.IPAddress()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsgwUAddr, err := net.ResolveUDPAddr(\"udp\", ip+gtpv2.GTPUPort)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tmock.raddr = sgwUAddr\n\t\t\t\tmock.teidOut = teid\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tgo mock.run(errCh)\n\n\tloggerCh <- fmt.Sprintf(\"Bearer modified with S-GW for Subscriber: %s\", session.IMSI)\n\treturn nil\n}\n\nfunc handleDeleteSessionResponse(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tloggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc.RemoveSession(session)\n\tdelWG.Done()\n\tloggerCh <- fmt.Sprintf(\"Session deleted with S-GW for Subscriber: %s\", session.IMSI)\n\treturn nil\n}\n"
  },
  {
    "path": "examples/mme/mock.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// getPGWIP is to get P-GW's IP address according to APN.\n//\n// DNS should be used in the real case, but here, to keep the example simple,\n// this function just returns IP address hard-coded in apnIPMap.\nfunc getPGWIP(apn string) (string, error) {\n\tapnIPMap := map[string]string{\n\t\t\"some-apn-1.example\": \"127.0.0.52\",\n\t\t\"some-apn-2.example\": \"127.0.0.53\",\n\t}\n\n\tif ip, ok := apnIPMap[apn]; ok {\n\t\treturn ip, nil\n\t}\n\treturn \"\", fmt.Errorf(\"got unknown APN: %s\", apn)\n}\n\n// dispatch sends subscribers to attachCh, which will be handled in handleAttach().\nfunc dispatch(subs []*gtpv2.Subscriber) {\n\tfor _, sub := range subs {\n\t\t// wait for 0-255ms before sending request (just for a little bit of reality)\n\t\t/*\n\t\t\tu8buf := make([]byte, 1)\n\t\t\trand.Read(u8buf)\n\t\t\ttime.Sleep(time.Duration(u8buf[0]) * time.Millisecond)\n\t\t*/\n\t\ttime.Sleep(100 * time.Millisecond)\n\n\t\tattachCh <- sub\n\t}\n}\n\n// handleAttach is to start the session creation on S11.\n// in the real case this should be called after the procedure on S1AP/NAS has been done.\nfunc handleAttach(raddr net.Addr, c *gtpv2.Conn, sub *gtpv2.Subscriber, br *gtpv2.Bearer) error {\n\t// remove previous session for the same subscriber if exists.\n\tsess, err := c.GetSessionByIMSI(sub.IMSI)\n\tif err != nil {\n\t\tswitch err.(type) {\n\t\tcase *gtpv2.UnknownIMSIError:\n\t\t\t// whole new session. just ignore.\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"got something unexpected: %w\", err)\n\t\t}\n\t} else {\n\t\tteid, err := sess.GetTEID(gtpv2.IFTypeS11S4SGWGTPC)\n\t\tif err != nil {\n\t\t\treturn gtpv2.ErrTEIDNotFound\n\t\t}\n\t\t// send Delete Session Request to cleanup sessions in S/P-GW.\n\t\tif _, err := c.DeleteSession(teid, sess); err != nil {\n\t\t\treturn fmt.Errorf(\"got something unexpected: %w\", err)\n\t\t}\n\t\tc.RemoveSession(sess)\n\t}\n\n\tpgwAddr, err := getPGWIP(br.APN)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar pci, pvi uint8\n\tif br.PCI {\n\t\tpci = 1\n\t}\n\tif br.PVI {\n\t\tpvi = 1\n\t}\n\tlocalIP := strings.Split(c.LocalAddr().String(), \":\")[0]\n\t_, _, err = c.CreateSession(\n\t\traddr,\n\t\tie.NewIMSI(sub.IMSI),\n\t\tie.NewMSISDN(sub.MSISDN),\n\t\tie.NewMobileEquipmentIdentity(sub.IMEI),\n\t\tie.NewUserLocationInformationStruct(\n\t\t\tie.NewCGI(sub.MCC, sub.MNC, sub.LAC, sub.CI),\n\t\t\tie.NewSAI(sub.MCC, sub.MNC, sub.LAC, sub.SAI),\n\t\t\tie.NewRAI(sub.MCC, sub.MNC, sub.LAC, sub.RAI),\n\t\t\tie.NewTAI(sub.MCC, sub.MNC, sub.TAI),\n\t\t\tie.NewECGI(sub.MCC, sub.MNC, sub.ECI),\n\t\t\tie.NewLAI(sub.MCC, sub.MNC, sub.LAC),\n\t\t\tie.NewMENBI(sub.MCC, sub.MNC, sub.MeNBI),\n\t\t\tie.NewEMENBI(sub.MCC, sub.MNC, sub.EMeNBI),\n\t\t),\n\t\tie.NewRATType(sub.RATType),\n\t\tie.NewIndicationFromOctets(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n\t\tc.NewSenderFTEID(localIP, \"\"),\n\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPC, 0, pgwAddr, \"\").WithInstance(1),\n\t\tie.NewAccessPointName(br.APN),\n\t\tie.NewSelectionMode(gtpv2.SelectionModeMSorNetworkProvidedAPNSubscribedVerified),\n\t\tie.NewPDNType(gtpv2.PDNTypeIPv4),\n\t\tie.NewPDNAddressAllocation(\"0.0.0.0\"),\n\t\tie.NewAPNRestriction(gtpv2.APNRestrictionNoExistingContextsorRestriction),\n\t\tie.NewAggregateMaximumBitRate(0, 0),\n\t\tie.NewBearerContext(\n\t\t\tie.NewEPSBearerID(br.EBI),\n\t\t\tie.NewBearerQoS(pci, br.PL, pvi, br.QCI, br.MBRUL, br.MBRDL, br.GBRUL, br.GBRDL),\n\t\t),\n\t\tie.NewFullyQualifiedCSID(localIP, 1),\n\t\tie.NewServingNetwork(sub.MCC, sub.MNC),\n\t\tie.NewUETimeZone(9*time.Hour, 0),\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nvar (\n\tuConn   *gtpv1.UPlaneConn\n\tpayload = []byte{ // ICMP Echo to 8.8.8.8 over IP(src will be replaced), checksum is invalid.\n\t\t// IP\n\t\t0x45, 0x00, 0x00, 0x54, 0x00, 0x01, 0x40, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t0x08, 0x08, 0x08, 0x08,\n\t\t// ICMP\n\t\t0x08, 0x00, 0x93, 0x6a, 0x00, 0x01, 0x00, 0x01, 0xdf, 0xd5, 0x2c, 0x00,\n\t\t0x00, 0x00, 0x00, 0x00, 0x99, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,\n\t\t0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,\n\t\t0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,\n\t\t0x34, 0x35, 0x36, 0x37,\n\t}\n)\n\ntype mockUEeNB struct {\n\traddr net.Addr\n\n\tsubscriberIP string\n\tteidOut      uint32\n\tpayload      []byte\n}\n\nfunc (m mockUEeNB) run(errCh chan error) {\n\tgo func(teid uint32, payload []byte, raddr net.Addr) {\n\t\tfor {\n\t\t\tcopy(payload[12:16], net.ParseIP(m.subscriberIP).To4())\n\t\t\tif _, err := uConn.WriteToGTP(teid, m.payload, raddr); err != nil {\n\t\t\t\terrCh <- err\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttime.Sleep(3 * time.Second)\n\t\t}\n\t}(m.teidOut, m.payload, m.raddr)\n\n\tgo once.Do(func() {\n\t\tbuf := make([]byte, 1500)\n\t\tfor {\n\t\t\tif uConn == nil {\n\t\t\t\terrCh <- errors.New(\"uConn conn is not open\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tn, raddr, _, err := uConn.ReadFromGTP(buf)\n\t\t\tif err != nil {\n\t\t\t\terrCh <- err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tloggerCh <- fmt.Sprintf(\"Received from %s: %x\", raddr, buf[:n])\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "examples/pgw/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command pgw is a dead simple implementation of P-GW only with GTP-related features.\n//\n// This example is not maintained well. Please see example/gw-tester/pgw for better implementation.\n//\n// P-GW follows the steps below if there's no unexpected events in the middle. Note\n// that the Gx procedure is just mocked to make it work in standalone manner.\n//\n// 1. Wait for Create Session Request from S-GW.\n//\n// 2. Send Create Session Response to S-GW if the required IEs are not missing, and\n// start listening on the interface specified with s5u flag.\n//\n// 3. If Modify Bearer Request comes from S-GW, update bearer information.\n//\n// 4. If T-PDU comes from S-GW, print the payload of encapsulated packets received,\n// and respond to it with payload(ICMP Echo Reply).\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// command-line arguments\nvar (\n\ts5c = flag.String(\"s5c\", \"127.0.0.52\", \"IP for S5-C interface.\")\n\ts5u = flag.String(\"s5u\", \"127.0.0.4\", \"IP for S5-U interface.\")\n)\n\nfunc main() {\n\tflag.Parse()\n\tlog.SetPrefix(\"[P-GW] \")\n\n\ts5cAddr, err := net.ResolveUDPAddr(\"udp\", *s5c+gtpv2.GTPCPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\t// start listening on the specified IP:Port.\n\ts5cConn := gtpv2.NewConn(s5cAddr, gtpv2.IFTypeS5S8PGWGTPC, 0)\n\tgo func() {\n\t\tif err := s5cConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving C-Plane on %s\", s5cAddr)\n\n\t// register handlers for ALL the message you expect remote endpoint to send.\n\ts5cConn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionRequest: handleCreateSessionRequest,\n\t\tmessage.MsgTypeDeleteSessionRequest: handleDeleteSessionRequest,\n\t})\n\n\ts5uAddr, err := net.ResolveUDPAddr(\"udp\", *s5u+gtpv2.GTPUPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tuConn = gtpv1.NewUPlaneConn(s5uAddr)\n\tdefer uConn.Close()\n\n\tgo func() {\n\t\tif err = uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving U-Plane on %s\", s5uAddr)\n\n\tfor {\n\t\tselect {\n\t\tcase str := <-loggerCh:\n\t\t\tlog.Printf(\"%s\", str)\n\t\tcase err := <-errCh:\n\t\t\tlog.Printf(\"Warning: %s\", err)\n\t\tcase <-time.After(10 * time.Second):\n\t\t\tvar activeIMSIs []string\n\t\t\tfor _, sess := range s5cConn.Sessions() {\n\t\t\t\tif !sess.IsActive() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tactiveIMSIs = append(activeIMSIs, sess.IMSI)\n\t\t\t}\n\t\t\tif len(activeIMSIs) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tlog.Println(\"Active Subscribers:\")\n\t\t\tfor _, imsi := range activeIMSIs {\n\t\t\t\tlog.Printf(\"\\t%s\", imsi)\n\t\t\t}\n\t\t\tactiveIMSIs = nil\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/pgw/pgw.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// getSubscriberIP is to get IP address to be assigned to the subscriber.\n//\n// In the real case, P-GW may ask AAA and PCRF retrieve required information for subscriber,\n// but here, to keep the example simple, this just returns subscriber's IP address defined in\n// the map \"subIPMap\".\nfunc getSubscriberIP(sub *gtpv2.Subscriber) (string, error) {\n\tsubIPMap := map[string]string{\n\t\t\"123451234567891\": \"10.10.10.1\",\n\t\t\"123451234567892\": \"10.10.10.2\",\n\t\t\"123451234567893\": \"10.10.10.3\",\n\t\t\"123451234567894\": \"10.10.10.4\",\n\t\t\"123451234567895\": \"10.10.10.5\",\n\t}\n\n\tif ip, ok := subIPMap[sub.IMSI]; ok {\n\t\treturn ip, nil\n\t}\n\treturn \"\", fmt.Errorf(\"subscriber %s not found\", sub.IMSI)\n}\n\nvar (\n\tloggerCh = make(chan string)\n\terrCh    = make(chan error)\n\n\tuConn *gtpv1.UPlaneConn\n)\n\nfunc handleCreateSessionRequest(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tloggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsReqFromSGW := msg.(*message.CreateSessionRequest)\n\n\t// keep session information retrieved from the message.\n\tsession := gtpv2.NewSession(sgwAddr, &gtpv2.Subscriber{Location: &gtpv2.Location{}})\n\tbearer := session.GetDefaultBearer()\n\tvar err error\n\tif imsiIE := csReqFromSGW.IMSI; imsiIE != nil {\n\t\timsi, err := imsiIE.IMSI()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.IMSI = imsi\n\n\t\t// remove previous session for the same subscriber if exists.\n\t\tsess, err := c.GetSessionByIMSI(imsi)\n\t\tif err != nil {\n\t\t\tswitch err.(type) {\n\t\t\tcase *gtpv2.UnknownIMSIError:\n\t\t\t\t// whole new session. just ignore.\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"got something unexpected: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\tc.RemoveSession(sess)\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.IMSI}\n\t}\n\tif msisdnIE := csReqFromSGW.MSISDN; msisdnIE != nil {\n\t\tsession.MSISDN, err = msisdnIE.MSISDN()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MSISDN}\n\t}\n\tif meiIE := csReqFromSGW.MEI; meiIE != nil {\n\t\tsession.IMEI, err = meiIE.MobileEquipmentIdentity()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MobileEquipmentIdentity}\n\t}\n\tif apnIE := csReqFromSGW.APN; apnIE != nil {\n\t\tbearer.APN, err = apnIE.AccessPointName()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.AccessPointName}\n\t}\n\tif netIE := csReqFromSGW.ServingNetwork; netIE != nil {\n\t\tsession.MNC, err = netIE.MNC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.ServingNetwork}\n\t}\n\tif ratIE := csReqFromSGW.RATType; ratIE != nil {\n\t\tsession.RATType, err = ratIE.RATType()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.RATType}\n\t}\n\tif fteidcIE := csReqFromSGW.SenderFTEIDC; fteidcIE != nil {\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsession.AddTEID(gtpv2.IFTypeS5S8SGWGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\tvar teidOut uint32\n\tif brCtxIE := csReqFromSGW.BearerContextsToBeCreated; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.EPSBearerID:\n\t\t\t\tbearer.EBI, err = childIE.EPSBearerID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tit, err := childIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tteidOut, err := childIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, teidOut)\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tbearer.SubscriberIP, err = getSubscriberIP(session.Subscriber)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcIP := strings.Split(c.LocalAddr().String(), \":\")[0]\n\tuIP := strings.Split(*s5u, \":\")[0]\n\ts5cFTEID := c.NewSenderFTEID(cIP, \"\").WithInstance(1)\n\ts5uFTEID := uConn.NewFTEID(gtpv2.IFTypeS5S8PGWGTPU, uIP, \"\").WithInstance(2)\n\ts5sgwTEID, err := session.GetTEID(gtpv2.IFTypeS5S8SGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcsRspFromPGW := message.NewCreateSessionResponse(\n\t\ts5sgwTEID, 0,\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\ts5cFTEID,\n\t\tie.NewPDNAddressAllocation(bearer.SubscriberIP),\n\t\tie.NewAPNRestriction(gtpv2.APNRestrictionPublic2),\n\t\tie.NewBearerContext(\n\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\tie.NewEPSBearerID(bearer.EBI),\n\t\t\ts5uFTEID,\n\t\t\tie.NewChargingID(bearer.ChargingID),\n\t\t),\n\t)\n\tif csReqFromSGW.SGWFQCSID != nil {\n\t\tcsRspFromPGW.PGWFQCSID = ie.NewFullyQualifiedCSID(cIP, 1)\n\t}\n\tsession.AddTEID(gtpv2.IFTypeS5S8PGWGTPC, s5cFTEID.MustTEID())\n\tsession.AddTEID(gtpv2.IFTypeS5S8PGWGTPU, s5uFTEID.MustTEID())\n\n\tif err := c.RespondTo(sgwAddr, csReqFromSGW, csRspFromPGW); err != nil {\n\t\treturn err\n\t}\n\n\ts5pgwTEID, err := session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\tc.RegisterSession(s5pgwTEID, session)\n\n\t// don't forget to activate and add session created to the session list\n\tif err := session.Activate(); err != nil {\n\t\treturn err\n\t}\n\n\tgo func() {\n\t\tbuf := make([]byte, 1500)\n\t\tfor {\n\t\t\tn, raddr, _, err := uConn.ReadFromGTP(buf)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trsp := make([]byte, n)\n\t\t\t// update message type and checksum\n\t\t\tcopy(rsp, buf[:n])\n\t\t\trsp[20] = 0\n\t\t\trsp[22] = 0x9b\n\t\t\t// swap IP\n\t\t\tcopy(rsp[12:16], buf[16:20])\n\t\t\tcopy(rsp[16:20], buf[12:16])\n\n\t\t\tif _, err := uConn.WriteToGTP(teidOut, rsp, raddr); err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}()\n\n\tloggerCh <- fmt.Sprintf(\"Session created with S-GW for subscriber: %s;\\n\\tS5C S-GW: %s, TEID->: %#x, TEID<-: %#x\",\n\t\tsession.Subscriber.IMSI, sgwAddr, s5sgwTEID, s5pgwTEID,\n\t)\n\treturn nil\n}\n\nfunc handleDeleteSessionRequest(c *gtpv2.Conn, sgwAddr net.Addr, msg message.Message) error {\n\tloggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), sgwAddr)\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tsession, err := c.GetSessionByTEID(msg.TEID(), sgwAddr)\n\tif err != nil {\n\t\tdsr := message.NewDeleteSessionResponse(\n\t\t\t0, 0,\n\t\t\tie.NewCause(gtpv2.CauseIMSIIMEINotKnown, 0, 0, 0, nil),\n\t\t)\n\t\tif err := c.RespondTo(sgwAddr, msg, dsr); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn err\n\t}\n\n\t// respond to S-GW with DeleteSessionResponse.\n\tteid, err := session.GetTEID(gtpv2.IFTypeS5S8SGWGTPC)\n\tif err != nil {\n\t\tloggerCh <- fmt.Sprintf(\"Error: %v\", err)\n\t\treturn nil\n\t}\n\tdsr := message.NewDeleteSessionResponse(\n\t\tteid, 0,\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t)\n\tif err := c.RespondTo(sgwAddr, msg, dsr); err != nil {\n\t\treturn err\n\t}\n\n\tloggerCh <- fmt.Sprintf(\"Session deleted for Subscriber: %s\", session.IMSI)\n\tc.RemoveSession(session)\n\treturn nil\n}\n"
  },
  {
    "path": "examples/sgw/main.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command sgw is a dead simple implementation of S-GW only with GTP-related features.\n//\n// S-GW follows the steps below if there's no unexpected events in the middle.\n//\n// 1. Start listening on S11 interface.\n//\n// 2. If MME connects to S-GW with Create Session Request, S-GW sends Create Session Request\n// to P-GW whose IP is specified by MME with F-TEID IE.\n//\n// 3. Wait for Create Session Response coming from P-GW with Cause=\"request accepted\", and\n// other IEs required are properly set.\n//\n// 4. Respond to MME with Create Session Response. Here the C-Plane Session is considered to\n// be created properly.\n//\n// 5. If MME sends Modify Bearer Request with eNB information inside, set incoming TEID to\n// Bearer and start listening on U-Plane.\n//\n// 6. If some U-Plane message comes from eNB/P-GW, relay it to P-GW/eNB with TEID and IP\n// properly set as told while exchanging the C-Plane signals.\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// command-line arguments and global variables\nvar (\n\ts11 = flag.String(\"s11\", \"127.0.0.112\", \"local IP on S11 interface.\")\n\ts5c = flag.String(\"s5c\", \"127.0.0.51\", \"local IP on S5-C interface.\")\n\ts1u = flag.String(\"s1u\", \"127.0.0.2\", \"local IP on S1-U interface.\")\n\ts5u = flag.String(\"s5u\", \"127.0.0.3\", \"local IP on S5-U interface.\")\n\n\tsgw *sGateway\n)\n\ntype sGateway struct {\n\ts11Conn, s5cConn *gtpv2.Conn\n\ts1uConn, s5uConn *gtpv1.UPlaneConn\n\n\tloggerCh chan string\n\terrCh    chan error\n}\n\nfunc newSGW(s11, s5c, s1u, s5u net.Addr) (*sGateway, error) {\n\ts := &sGateway{\n\t\tloggerCh: make(chan string),\n\t\terrCh:    make(chan error),\n\t}\n\n\tctx := context.Background()\n\n\tvar err error\n\ts.s11Conn = gtpv2.NewConn(s11, gtpv2.IFTypeS11S4SGWGTPC, 0)\n\tgo func() {\n\t\tif err = s.s11Conn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving on %s\", s11)\n\n\ts.s5cConn = gtpv2.NewConn(s5c, gtpv2.IFTypeS5S8SGWGTPC, 0)\n\tgo func() {\n\t\tif err = s.s5cConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\tlog.Printf(\"Started serving on %s\", s5c)\n\n\ts.s1uConn = gtpv1.NewUPlaneConn(s1u)\n\tgo func() {\n\t\tif err = s.s1uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\n\tgo func() {\n\t\ts.s5uConn = gtpv1.NewUPlaneConn(s5u)\n\t\tif err = s.s5uConn.ListenAndServe(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\n\treturn s, nil\n}\n\nfunc (s *sGateway) run() error {\n\tdefer func() {\n\t\ts.s11Conn.Close()\n\t\ts.s5cConn.Close()\n\t}()\n\n\t// wait for events(logs, errors, timers).\n\tfor {\n\t\tselect {\n\t\tcase str := <-s.loggerCh:\n\t\t\tlog.Println(str)\n\t\tcase err := <-s.errCh:\n\t\t\tlog.Printf(\"Warning: %v\", err)\n\t\tcase <-time.After(10 * time.Second):\n\t\t\tvar activeIMSIs []string\n\t\t\tfor _, sess := range s.s11Conn.Sessions() {\n\t\t\t\tif !sess.IsActive() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tactiveIMSIs = append(activeIMSIs, sess.IMSI)\n\t\t\t}\n\t\t\tif len(activeIMSIs) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tlog.Println(\"Active Subscribers:\")\n\t\t\tfor _, imsi := range activeIMSIs {\n\t\t\t\tlog.Printf(\"\\t%s\", imsi)\n\t\t\t}\n\t\t\tactiveIMSIs = nil\n\t\t}\n\t}\n}\n\nfunc main() {\n\tflag.Parse()\n\tlog.SetPrefix(\"[S-GW] \")\n\n\t// resolve specified IP:Port as net.UDPAddr.\n\ts11, err := net.ResolveUDPAddr(\"udp\", *s11+gtpv2.GTPCPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\ts5c, err := net.ResolveUDPAddr(\"udp\", *s5c+gtpv2.GTPCPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\ts1u, err := net.ResolveUDPAddr(\"udp\", *s1u+gtpv2.GTPUPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\ts5u, err := net.ResolveUDPAddr(\"udp\", *s5u+gtpv2.GTPUPort)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tsgw, err = newSGW(s11, s5c, s1u, s5u)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\t// register handlers for ALL the message you expect remote endpoint to send.\n\tsgw.s11Conn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionRequest: handleCreateSessionRequest,\n\t\tmessage.MsgTypeModifyBearerRequest:  handleModifyBearerRequest,\n\t\tmessage.MsgTypeDeleteSessionRequest: handleDeleteSessionRequest,\n\t\tmessage.MsgTypeDeleteBearerResponse: handleDeleteBearerResponse,\n\t})\n\tsgw.s5cConn.AddHandlers(map[uint8]gtpv2.HandlerFunc{\n\t\tmessage.MsgTypeCreateSessionResponse: handleCreateSessionResponse,\n\t\tmessage.MsgTypeDeleteSessionResponse: handleDeleteSessionResponse,\n\t\tmessage.MsgTypeDeleteBearerRequest:   handleDeleteBearerRequest,\n\t})\n\n\tlog.Fatal(sgw.run())\n}\n"
  },
  {
    "path": "examples/sgw/s11.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Command sgw is a dead simple implementation of S-GW only with GTP-related features.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc handleCreateSessionRequest(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\n\ts11Session := gtpv2.NewSession(mmeAddr, &gtpv2.Subscriber{Location: &gtpv2.Location{}})\n\ts11Bearer := s11Session.GetDefaultBearer()\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsReqFromMME := msg.(*message.CreateSessionRequest)\n\n\tvar pgwAddrString string\n\tif teidIE := csReqFromMME.PGWS5S8FTEIDC; teidIE != nil {\n\t\tip, err := teidIE.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpgwAddrString = ip + gtpv2.GTPCPort\n\n\t\tteid, err := teidIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts11Session.AddTEID(gtpv2.IFTypeS5S8PGWGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\tif senderIE := csReqFromMME.SenderFTEIDC; senderIE != nil {\n\t\tteid, err := senderIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts11Session.AddTEID(gtpv2.IFTypeS11MMEGTPC, teid)\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\tladdr, err := net.ResolveUDPAddr(\"udp\", *s5c+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn err\n\t}\n\traddr, err := net.ResolveUDPAddr(\"udp\", pgwAddrString)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// keep session information retrieved from the message.\n\t// XXX - should return error if required IE is missing.\n\tif imsiIE := csReqFromMME.IMSI; imsiIE != nil {\n\t\timsi, err := imsiIE.IMSI()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// remove previous session for the same subscriber if exists.\n\t\tsess, err := s11Conn.GetSessionByIMSI(imsi)\n\t\tif err != nil {\n\t\t\tswitch err.(type) {\n\t\t\tcase *gtpv2.UnknownIMSIError:\n\t\t\t\t// whole new session. just ignore.\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"got something unexpected: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\ts11Conn.RemoveSession(sess)\n\t\t}\n\n\t\ts11Session.IMSI = imsi\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.IMSI}\n\t}\n\tif msisdnIE := csReqFromMME.MSISDN; msisdnIE != nil {\n\t\ts11Session.MSISDN, err = msisdnIE.MSISDN()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MSISDN}\n\t}\n\tif meiIE := csReqFromMME.MEI; meiIE != nil {\n\t\ts11Session.IMEI, err = meiIE.MobileEquipmentIdentity()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.MobileEquipmentIdentity}\n\t}\n\tif apnIE := csReqFromMME.APN; apnIE != nil {\n\t\ts11Bearer.APN, err = apnIE.AccessPointName()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.AccessPointName}\n\t}\n\tif netIE := csReqFromMME.ServingNetwork; netIE != nil {\n\t\ts11Session.MCC, err = netIE.MCC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts11Session.MNC, err = netIE.MNC()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.ServingNetwork}\n\t}\n\tif ratIE := csReqFromMME.RATType; ratIE != nil {\n\t\ts11Session.RATType, err = ratIE.RATType()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.RATType}\n\t}\n\n\ts11IP, _, err := net.SplitHostPort(*s11 + gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get IP for S11: %w\", err)\n\t}\n\tsenderFTEID := s11Conn.NewSenderFTEID(s11IP, \"\")\n\ts11sgwTEID := senderFTEID.MustTEID()\n\ts11Conn.RegisterSession(s11sgwTEID, s11Session)\n\n\ts5cIP := laddr.IP.String()\n\ts5uIP, _, err := net.SplitHostPort(*s5u + gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5cFTEID := sgw.s5cConn.NewSenderFTEID(s5cIP, \"\")\n\ts5uFTEID := sgw.s5uConn.NewFTEID(gtpv2.IFTypeS5S8SGWGTPU, s5uIP, \"\").WithInstance(2)\n\n\ts5Session, seq, err := sgw.s5cConn.CreateSession(\n\t\traddr,\n\t\tcsReqFromMME.IMSI, csReqFromMME.MSISDN, csReqFromMME.MEI, csReqFromMME.ServingNetwork,\n\t\tcsReqFromMME.RATType, csReqFromMME.IndicationFlags, s5cFTEID, csReqFromMME.PGWS5S8FTEIDC,\n\t\tcsReqFromMME.APN, csReqFromMME.SelectionMode, csReqFromMME.PDNType, csReqFromMME.PAA,\n\t\tcsReqFromMME.APNRestriction, csReqFromMME.AMBR, csReqFromMME.ULI,\n\t\tie.NewBearerContext(\n\t\t\tie.NewEPSBearerID(5),\n\t\t\ts5uFTEID,\n\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0, 0, 0, 0),\n\t\t),\n\t\tcsReqFromMME.MMEFQCSID,\n\t\tie.NewFullyQualifiedCSID(s5uIP, 1).WithInstance(1),\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5Session.AddTEID(s5uFTEID.MustInterfaceType(), s5uFTEID.MustTEID())\n\tsgw.s5cConn.RegisterSession(s5cFTEID.MustTEID(), s5Session)\n\n\tsgw.loggerCh <- fmt.Sprintf(\"Sent Create Session Request to %s for %s\", pgwAddrString, s5Session.IMSI)\n\n\tvar csRspFromSGW *message.CreateSessionResponse\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\tincomingMsg, err := s11Session.WaitMessage(seq, 5*time.Second)\n\tif err != nil {\n\t\tcsRspFromSGW = message.NewCreateSessionResponse(\n\t\t\ts11mmeTEID, 0,\n\t\t\tie.NewCause(gtpv2.CauseNoResourcesAvailable, 0, 0, 0, nil),\n\t\t)\n\n\t\tif err := s11Conn.RespondTo(mmeAddr, csReqFromMME, csRspFromSGW); err != nil {\n\t\t\ts11Conn.RemoveSession(s11Session)\n\t\t\treturn err\n\t\t}\n\t\tsgw.loggerCh <- fmt.Sprintf(\n\t\t\t\"Sent %s with failure code: %d, target subscriber: %s\",\n\t\t\tcsRspFromSGW.MessageTypeName(), gtpv2.CausePGWNotResponding, s11Session.IMSI,\n\t\t)\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tvar csRspFromPGW *message.CreateSessionResponse\n\tswitch m := incomingMsg.(type) {\n\tcase *message.CreateSessionResponse:\n\t\t// move forward\n\t\tcsRspFromPGW = m\n\tdefault:\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn &gtpv2.UnexpectedTypeError{Msg: incomingMsg}\n\t}\n\t// if everything in CreateSessionResponse seems OK, relay it to MME.\n\ts1uIP, _, err := net.SplitHostPort(*s1u + gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get IP for S1-U: %w\", err)\n\t}\n\ts1usgwFTEID := sgw.s1uConn.NewFTEID(gtpv2.IFTypeS1USGWGTPU, s1uIP, \"\")\n\tcsRspFromSGW = csRspFromPGW\n\tcsRspFromSGW.SenderFTEIDC = senderFTEID\n\tcsRspFromSGW.SGWFQCSID = ie.NewFullyQualifiedCSID(s1uIP, 1).WithInstance(1)\n\tcsRspFromSGW.BearerContextsCreated[0].Add(s1usgwFTEID)\n\tcsRspFromSGW.BearerContextsCreated[0].Remove(ie.ChargingID, 0)\n\tcsRspFromSGW.SetTEID(s11mmeTEID)\n\tcsRspFromSGW.SetLength()\n\n\tif err := s11Conn.RespondTo(mmeAddr, csReqFromMME, csRspFromSGW); err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\ts11Session.AddTEID(senderFTEID.MustInterfaceType(), s11sgwTEID)\n\ts11Session.AddTEID(s1usgwFTEID.MustInterfaceType(), s1usgwFTEID.MustTEID())\n\n\ts5cpgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\ts5csgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8SGWGTPC)\n\tif err != nil {\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tif err := s11Session.Activate(); err != nil {\n\t\tsgw.loggerCh <- fmt.Sprintf(\"Error: %v\", err)\n\t\ts11Conn.RemoveSession(s11Session)\n\t\treturn err\n\t}\n\n\tsgw.loggerCh <- fmt.Sprintf(\n\t\t\"Session created with MME and P-GW for Subscriber: %s;\\n\\tS11 MME:  %s, TEID->: %#x, TEID<-: %#x\\n\\tS5C P-GW: %s, TEID->: %#x, TEID<-: %#x\",\n\t\ts5Session.Subscriber.IMSI, mmeAddr, s11mmeTEID, s11sgwTEID, pgwAddrString, s5cpgwTEID, s5csgwTEID,\n\t)\n\treturn nil\n}\n\nfunc handleModifyBearerRequest(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\n\ts11Session, err := s11Conn.GetSessionByTEID(msg.TEID(), mmeAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5cSession, err := sgw.s5cConn.GetSessionByIMSI(s11Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts1uBearer := s11Session.GetDefaultBearer()\n\ts5uBearer := s5cSession.GetDefaultBearer()\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tmbReqFromMME := msg.(*message.ModifyBearerRequest)\n\tif brCtxIE := mbReqFromMME.BearerContextsToBeModified; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.Indication:\n\t\t\t\t// do nothing in this example.\n\t\t\t\t// S-GW should change its beahavior based on indication flags like;\n\t\t\t\t//  - pass Modify Bearer Request to P-GW if handover is indicated.\n\t\t\t\t//  - XXX...\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif err := handleFTEIDU(childIE, s11Session, s1uBearer); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts1usgwTEID, err := s11Session.GetTEID(gtpv2.IFTypeS1USGWGTPU)\n\tif err != nil {\n\t\treturn err\n\t}\n\ts5usgwTEID, err := s5cSession.GetTEID(gtpv2.IFTypeS5S8SGWGTPU)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := sgw.s1uConn.RelayTo(\n\t\tsgw.s5uConn, s1usgwTEID, s5uBearer.OutgoingTEID(), s5uBearer.RemoteAddress(),\n\t); err != nil {\n\t\treturn err\n\t}\n\tif err := sgw.s5uConn.RelayTo(\n\t\tsgw.s1uConn, s5usgwTEID, s1uBearer.OutgoingTEID(), s1uBearer.RemoteAddress(),\n\t); err != nil {\n\t\treturn err\n\t}\n\n\ts1uIP, _, err := net.SplitHostPort(*s1u + gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn err\n\t}\n\tmbRspFromSGW := message.NewModifyBearerResponse(\n\t\ts11mmeTEID, 0,\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\tie.NewBearerContext(\n\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\tie.NewEPSBearerID(s1uBearer.EBI),\n\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, s1usgwTEID, s1uIP, \"\"),\n\t\t),\n\t)\n\n\tif err := s11Conn.RespondTo(mmeAddr, msg, mbRspFromSGW); err != nil {\n\t\treturn err\n\t}\n\n\tsgw.loggerCh <- fmt.Sprintf(\n\t\t\"Started listening on U-Plane for Subscriber: %s;\\n\\tS1-U: %s\\n\\tS5-U: %s\",\n\t\ts11Session.IMSI, *s1u, *s5u,\n\t)\n\treturn nil\n}\n\nfunc handleDeleteSessionRequest(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tdsReqFromMME := msg.(*message.DeleteSessionRequest)\n\n\ts11Session, err := s11Conn.GetSessionByTEID(msg.TEID(), mmeAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5Session, err := sgw.s5cConn.GetSessionByIMSI(s11Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5cpgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tseq, err := sgw.s5cConn.DeleteSession(\n\t\ts5cpgwTEID, s5Session,\n\t\tie.NewEPSBearerID(s5Session.GetDefaultBearer().EBI),\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar dsRspFromSGW *message.DeleteSessionResponse\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tincomingMsg, err := s11Session.WaitMessage(seq, 5*time.Second)\n\tif err != nil {\n\t\tdsRspFromSGW = message.NewDeleteSessionResponse(\n\t\t\ts11mmeTEID, 0,\n\t\t\tie.NewCause(gtpv2.CausePGWNotResponding, 0, 0, 0, nil),\n\t\t)\n\n\t\tif err := s11Conn.RespondTo(mmeAddr, dsReqFromMME, dsRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsgw.loggerCh <- fmt.Sprintf(\n\t\t\t\"Sent %s with failure code: %d, target subscriber: %s\",\n\t\t\tdsRspFromSGW.MessageTypeName(), gtpv2.CausePGWNotResponding, s11Session.IMSI,\n\t\t)\n\t\treturn err\n\t}\n\n\t// use the cause as it is.\n\tswitch m := incomingMsg.(type) {\n\tcase *message.DeleteSessionResponse:\n\t\t// move forward\n\t\tdsRspFromSGW = m\n\tdefault:\n\t\treturn &gtpv2.UnexpectedTypeError{Msg: incomingMsg}\n\t}\n\n\tdsRspFromSGW.SetTEID(s11mmeTEID)\n\tif err := s11Conn.RespondTo(mmeAddr, msg, dsRspFromSGW); err != nil {\n\t\treturn err\n\t}\n\n\tsgw.loggerCh <- fmt.Sprintf(\"Session deleted for Subscriber: %s\", s11Session.IMSI)\n\ts11Conn.RemoveSession(s11Session)\n\n\treturn nil\n}\n\nfunc handleDeleteBearerResponse(s11Conn *gtpv2.Conn, mmeAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), mmeAddr)\n\n\ts11Session, err := s11Conn.GetSessionByTEID(msg.TEID(), mmeAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5Session, err := sgw.s5cConn.GetSessionByIMSI(s11Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := gtpv2.PassMessageTo(s5Session, msg, 5*time.Second); err != nil {\n\t\treturn err\n\t}\n\n\t// remove bearer in handleDeleteBearerRequest instead of doing here,\n\t// as Delete Bearer Request does not necessarily have EBI.\n\treturn nil\n}\n\nfunc handleFTEIDU(fteiduIE *ie.IE, session *gtpv2.Session, bearer *gtpv2.Bearer) error {\n\tif fteiduIE.Type != ie.FullyQualifiedTEID {\n\t\treturn &gtpv2.UnexpectedIEError{IEType: fteiduIE.Type}\n\t}\n\n\tip, err := fteiduIE.IPAddress()\n\tif err != nil {\n\t\treturn err\n\t}\n\taddr, err := net.ResolveUDPAddr(\"udp\", ip+gtpv2.GTPUPort)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbearer.SetRemoteAddress(addr)\n\n\tteid, err := fteiduIE.TEID()\n\tif err != nil {\n\t\treturn err\n\t}\n\tbearer.SetOutgoingTEID(teid)\n\n\tit, err := fteiduIE.InterfaceType()\n\tif err != nil {\n\t\treturn err\n\t}\n\tsession.AddTEID(it, teid)\n\treturn nil\n}\n"
  },
  {
    "path": "examples/sgw/s5.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc handleCreateSessionResponse(s5cConn *gtpv2.Conn, pgwAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), pgwAddr)\n\n\ts5Session, err := s5cConn.GetSessionByTEID(msg.TEID(), pgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tcsRspFromPGW := msg.(*message.CreateSessionResponse)\n\n\t// check Cause value first.\n\tif causeIE := csRspFromPGW.Cause; causeIE != nil {\n\t\tcause, err := causeIE.Cause()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\ts5cConn.RemoveSession(s5Session)\n\t\t\t// this is not such a fatal error worth stopping the whole program.\n\t\t\t// in the real case it is better to take some action based on the Cause, though.\n\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\tMsgType: csRspFromPGW.MessageTypeName(),\n\t\t\t\tCause:   cause,\n\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", s5Session.IMSI),\n\t\t\t}\n\t\t}\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{\n\t\t\tType: ie.Cause,\n\t\t}\n\t}\n\n\tbearer := s5Session.GetDefaultBearer()\n\t// retrieve values that P-GW gave.\n\tif paaIE := csRspFromPGW.PAA; paaIE != nil {\n\t\tip, err := paaIE.IPAddress()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tbearer.SubscriberIP = ip\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.PDNAddressAllocation}\n\t}\n\tif fteidcIE := csRspFromPGW.PGWS5S8FTEIDC; fteidcIE != nil {\n\t\tit, err := fteidcIE.InterfaceType()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tteid, err := fteidcIE.TEID()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ts5Session.AddTEID(it, teid)\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.FullyQualifiedTEID}\n\t}\n\n\tif brCtxIE := csRspFromPGW.BearerContextsCreated; brCtxIE != nil {\n\t\tfor _, childIE := range brCtxIE[0].ChildIEs {\n\t\t\tswitch childIE.Type {\n\t\t\tcase ie.Cause:\n\t\t\t\tcause, err := childIE.Cause()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\t\t\ts5cConn.RemoveSession(s5Session)\n\t\t\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\t\t\tMsgType: csRspFromPGW.MessageTypeName(),\n\t\t\t\t\t\tCause:   cause,\n\t\t\t\t\t\tMsg:     fmt.Sprintf(\"subscriber: %s\", s5Session.IMSI),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase ie.EPSBearerID:\n\t\t\t\tebi, err := childIE.EPSBearerID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tbearer.EBI = ebi\n\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\tif err := handleFTEIDU(childIE, s5Session, bearer); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase ie.ChargingID:\n\t\t\t\tcid, err := childIE.ChargingID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tbearer.ChargingID = cid\n\t\t\t}\n\t\t}\n\t} else {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.BearerContext}\n\t}\n\n\tif err := s5Session.Activate(); err != nil {\n\t\ts5cConn.RemoveSession(s5Session)\n\t\treturn err\n\t}\n\n\ts11Session, err := sgw.s11Conn.GetSessionByIMSI(s5Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := gtpv2.PassMessageTo(s11Session, csRspFromPGW, 5*time.Second); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc handleDeleteSessionResponse(s5cConn *gtpv2.Conn, pgwAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), pgwAddr)\n\n\ts5Session, err := s5cConn.GetSessionByTEID(msg.TEID(), pgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts11Session, err := sgw.s11Conn.GetSessionByIMSI(s5Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := gtpv2.PassMessageTo(s11Session, msg, 5*time.Second); err != nil {\n\t\treturn err\n\t}\n\n\t// even the cause indicates failure, session should be removed locally.\n\tsgw.loggerCh <- fmt.Sprintf(\"Session deleted for Subscriber: %s\", s5Session.IMSI)\n\ts5cConn.RemoveSession(s5Session)\n\treturn nil\n}\n\nfunc handleDeleteBearerRequest(s5cConn *gtpv2.Conn, pgwAddr net.Addr, msg message.Message) error {\n\tsgw.loggerCh <- fmt.Sprintf(\"Received %s from %s\", msg.MessageTypeName(), pgwAddr)\n\n\ts5Session, err := s5cConn.GetSessionByTEID(msg.TEID(), pgwAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts11Session, err := sgw.s11Conn.GetSessionByIMSI(s5Session.IMSI)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts5cpgwTEID, err := s5Session.GetTEID(gtpv2.IFTypeS5S8PGWGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ts11mmeTEID, err := s11Session.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// assert type to refer to the struct field specific to the message.\n\t// in general, no need to check if it can be type-asserted, as long as the MessageType is\n\t// specified correctly in AddHandler().\n\tdbReqFromPGW := msg.(*message.DeleteBearerRequest)\n\n\tvar dbRspFromSGW *message.DeleteBearerResponse\n\tvar ebi *ie.IE\n\tif ie := dbReqFromPGW.LinkedEBI; ie != nil {\n\t\tebi = ie\n\t}\n\tif e := dbReqFromPGW.EBIs; e != nil {\n\t\tebiIE := e[0]\n\t\t// shouldn't be both.\n\t\tif ebi != nil {\n\t\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\t\ts5cpgwTEID, 0,\n\t\t\t\tie.NewCause(gtpv2.CauseContextNotFound, 0, 0, 0, ebiIE),\n\t\t\t)\n\t\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"%T from %s had both Linked EBI and EBIs IE\",\n\t\t\t\tdbReqFromPGW, pgwAddr,\n\t\t\t)\n\t\t}\n\t\tebi = ebiIE\n\t}\n\n\tif ebi == nil {\n\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\ts5cpgwTEID, 0, ie.NewCause(gtpv2.CauseMandatoryIEMissing,\n\t\t\t\t0, 0, 0, ie.NewEPSBearerID(0),\n\t\t\t),\n\t\t)\n\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn err\n\t}\n\n\t// check if bearer associated with EBI exists or not.\n\t_, err = s5Session.LookupBearerByEBI(ebi.MustEPSBearerID())\n\tif err != nil {\n\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\ts5cpgwTEID, 0,\n\t\t\tie.NewCause(gtpv2.CauseContextNotFound, 0, 0, 0, nil),\n\t\t)\n\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn err\n\t}\n\n\t// forward to MME\n\tseq, err := sgw.s11Conn.DeleteBearer(s11mmeTEID, s11Session, ebi)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// wait for response from MME for 5 seconds\n\tincomingMsg, err := s5Session.WaitMessage(seq, 5*time.Second)\n\tif err != nil {\n\t\tdbRspFromSGW = message.NewDeleteBearerResponse(\n\t\t\ts5cpgwTEID, 0,\n\t\t\tie.NewCause(gtpv2.CauseNoResourcesAvailable, 0, 0, 0, nil),\n\t\t)\n\n\t\tif err := s5cConn.RespondTo(pgwAddr, dbReqFromPGW, dbRspFromSGW); err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// remove anyway, as P-GW no longer keeps bearer locally\n\t\ts5Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\t\ts11Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\t\treturn err\n\t}\n\n\tswitch m := incomingMsg.(type) {\n\tcase *message.DeleteBearerResponse:\n\t\t// move forward\n\t\tdbRspFromSGW = m\n\tdefault:\n\t\treturn &gtpv2.UnexpectedTypeError{Msg: incomingMsg}\n\t}\n\n\tdbRspFromSGW.SetTEID(s5cpgwTEID)\n\tif err := s5cConn.RespondTo(pgwAddr, msg, dbRspFromSGW); err != nil {\n\t\treturn err\n\t}\n\n\ts5Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\ts11Session.RemoveBearerByEBI(ebi.MustEPSBearerID())\n\n\treturn nil\n}\n"
  },
  {
    "path": "examples/utils/mac_local_host_enabler.sh",
    "content": "# This script will enable 127.0.0.1 up to 127.0.0.256 interfaces\nfor ((i=2;i<256;i++)) do \n  sudo ifconfig lo0 alias 127.0.0.$i up\ndone \n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/wmnsk/go-gtp\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/golang/protobuf v1.5.4\n\tgithub.com/google/go-cmp v0.7.0\n\tgithub.com/pascaldekloe/goe v0.1.1\n\tgithub.com/prometheus/client_golang v1.23.2\n\tgithub.com/vishvananda/netlink v1.3.1\n\tgolang.org/x/net v0.51.0\n\tgoogle.golang.org/grpc v1.79.2\n\tgopkg.in/yaml.v2 v2.4.0\n)\n\nrequire (\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/kr/text v0.2.0 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/prometheus/client_model v0.6.2 // indirect\n\tgithub.com/prometheus/common v0.67.5 // indirect\n\tgithub.com/prometheus/procfs v0.20.1 // indirect\n\tgithub.com/vishvananda/netns v0.0.5 // indirect\n\tgo.yaml.in/yaml/v2 v2.4.3 // indirect\n\tgolang.org/x/sys v0.41.0 // indirect\n\tgolang.org/x/text v0.34.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect\n\tgoogle.golang.org/protobuf v1.36.11 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=\ngithub.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=\ngithub.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/pascaldekloe/goe v0.1.1 h1:Ah6WQ56rZONR3RW3qWa2NCZ6JAVvSpUcoLBaOmYFt9Q=\ngithub.com/pascaldekloe/goe v0.1.1/go.mod h1:KSyfaxQOh0HZPjDP1FL/kFtbqYqrALJTaMafFUIccqU=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=\ngithub.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=\ngithub.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=\ngithub.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=\ngithub.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=\ngithub.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=\ngithub.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=\ngithub.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=\ngithub.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=\ngithub.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=\ngithub.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=\ngithub.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=\ngithub.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=\ngo.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=\ngo.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=\ngo.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=\ngo.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=\ngo.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=\ngo.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=\ngo.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=\ngo.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=\ngo.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=\ngo.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=\ngo.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=\ngo.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngo.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=\ngo.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=\ngolang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=\ngolang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=\ngolang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=\ngolang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=\ngolang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=\ngonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=\ngonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=\ngoogle.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=\ngoogle.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=\ngoogle.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=\ngoogle.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "gtp.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtp\n\nimport (\n\tv0msg \"github.com/wmnsk/go-gtp/gtpv0/message\"\n\tv1msg \"github.com/wmnsk/go-gtp/gtpv1/message\"\n\tv2msg \"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// Message is an interface that defines all versions of GTP message.\ntype Message interface {\n\tMarshalTo([]byte) error\n\tUnmarshalBinary(b []byte) error\n\tMarshalLen() int\n\tVersion() int\n\tMessageType() uint8\n\tMessageTypeName() string\n\n\t// deprecated\n\tSerializeTo([]byte) error\n\tDecodeFromBytes(b []byte) error\n}\n\n// Marshal returns the byte sequence generated from a Message instance.\n// Better to use (*MessageName).Marshal instead if you know the name of message to be serialized.\nfunc Marshal(m Message) ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// Parse decodes given bytes as Message.\nfunc Parse(b []byte) (Message, error) {\n\tif len(b) < 8 {\n\t\treturn nil, ErrTooShortToParse\n\t}\n\n\tswitch b[0] >> 5 {\n\tcase 0:\n\t\treturn v0msg.Parse(b)\n\tcase 1:\n\t\treturn v1msg.Parse(b)\n\tcase 2:\n\t\treturn v2msg.Parse(b)\n\tdefault:\n\t\treturn nil, ErrInvalidVersion\n\t}\n}\n"
  },
  {
    "path": "gtp_fuzz_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtp_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := gtp.Parse(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtp_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtp\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/pascaldekloe/goe/verify\"\n\n\tv0msg \"github.com/wmnsk/go-gtp/gtpv0/message\"\n\tv1msg \"github.com/wmnsk/go-gtp/gtpv1/message\"\n\tv2ie \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\tv2msg \"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nvar v0flow = struct {\n\tseq   uint16\n\tlabel uint16\n\ttid   uint64\n}{1, 0, 0x2143658709214355}\n\nfunc TestMessage(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  Message\n\t\tserialized  []byte\n\t}{\n\t\t{\n\t\t\t\"GTPv0 Echo Request\",\n\t\t\tv0msg.NewEchoRequest(v0flow.seq, v0flow.label, v0flow.tid),\n\t\t\t[]byte{\n\t\t\t\t0x1e, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,\n\t\t\t\t0xff, 0xff, 0xff, 0xff, 0x21, 0x43, 0x65, 0x87,\n\t\t\t\t0x09, 0x21, 0x43, 0x55,\n\t\t\t},\n\t\t}, {\n\t\t\t\"GTPv1 Echo Request\",\n\t\t\tv1msg.NewEchoRequest(0),\n\t\t\t[]byte{\n\t\t\t\t0x32, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00,\n\t\t\t},\n\t\t}, {\n\t\t\t\"GTPv2 Echo Request\",\n\t\t\tv2msg.NewEchoRequest(0, v2ie.NewRecovery(0x80)),\n\t\t\t[]byte{\n\t\t\t\t0x40, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"Encode/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := Marshal(c.structured)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"Parse/\"+c.description, func(t *testing.T) {\n\t\t\tv, err := Parse(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif got, want := v, c.structured; !verify.Values(t, \"\", got, want) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"MarshalLen/\"+c.description, func(t *testing.T) {\n\t\t\tif got, want := c.structured.MarshalLen(), len(c.serialized); got != want {\n\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"Interface/\"+c.description, func(t *testing.T) {\n\t\t\tdecoded, err := Parse(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif got, want := decoded.Version(), c.structured.Version(); got != want {\n\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t}\n\t\t\tif got, want := decoded.MessageType(), c.structured.MessageType(); got != want {\n\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t}\n\t\t\tif got, want := decoded.MessageTypeName(), c.structured.MessageTypeName(); got != want {\n\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv0/README.md",
    "content": "# v0: GTPv0 in Golang\n\nPackage v0 provides simple and painless handling of GTPv0 protocol in pure Golang.\n\n## Getting Started\n\nThis package is still under construction.\nSee the source codes for what you can do with the current implementation. \n\n### Creating a PDP Context as a client\n\n_NOT IMPLEMENTED YET!_\n\n### Waiting for a PDP Context to be created as a server\n\n_NOT IMPLEMENTED YET!_\n\n### Opening a U-Plane connection\n\n_NOT IMPLEMENTED YET!_\n\n## Supported Features\n\nThe following Messages marked with \"Yes\" are currently available with their own useful constructors.\n\n_Even there are some missing Messages, you can create any kind of Message by using `message.NewGeneric()`._\n\n### Messages\n\n| ID      | Name                                        | Supported |\n|---------|---------------------------------------------|-----------|\n| 0       | (Spare/Reserved)                            | -         |\n| 1       | Echo Request                                | Yes       |\n| 2       | Echo Response                               | Yes       |\n| 3       | Version Not Supported                       |           |\n| 4       | Node Alive Request                          |           |\n| 5       | Node Alive Response                         |           |\n| 6       | Redirection Request                         |           |\n| 7       | Redirection Response                        |           |\n| 8-15    | (Spare/Reserved)                            | -         |\n| 16      | Create PDP Context Request                  | Yes       |\n| 17      | Create PDP Context Response                 | Yes       |\n| 18      | Update PDP Context Request                  | Yes       |\n| 19      | Update PDP Context Response                 | Yes       |\n| 20      | Delete PDP Context Request                  | Yes       |\n| 21      | Delete PDP Context Response                 | Yes       |\n| 22      | Create AA PDP Context Request               |           |\n| 23      | Create AA PDP Context Response              |           |\n| 24      | Delete AA PDP Context Request               |           |\n| 25      | Delete AA PDP Context Response              |           |\n| 26      | Error Indication                            |           |\n| 27      | PDU Notification Request                    |           |\n| 28      | PDU Notification Response                   |           |\n| 29      | PDU Notification Reject Request             |           |\n| 30      | PDU Notification Reject Response            |           |\n| 31      | (Spare/Reserved)                            | -         |\n| 32      | Send Routeing Information for GPRS Request  |           |\n| 33      | Send Routeing Information for GPRS Response |           |\n| 34      | Failure Report Request                      |           |\n| 35      | Failure Report Response                     |           |\n| 36      | Note MS GPRS Present Request                |           |\n| 37      | Note MS GPRS Present Response               |           |\n| 38-47   | (Spare/Reserved)                            | -         |\n| 48      | Identification Request                      |           |\n| 49      | Identification Response                     |           |\n| 50      | SGSN Context Request                        |           |\n| 51      | SGSN Context Response                       |           |\n| 52      | SGSN Context Acknowledge                    |           |\n| 53-239  | (Spare/Reserved)                            | -         |\n| 240     | Data Record Transfer Request                |           |\n| 241     | Data Record Transfer Response               |           |\n| 242-254 | (Spare/Reserved)                            | -         |\n| 255     | T-PDU                                       | Yes       |\n\n### Information Elements\n\nThe following Information Elements marked with \"Yes\" are currently available with their own useful constructors.\n\n_Even there are some missing IEs, you can create any kind of IEs by using `ie.New()` function or by initializing ie.IE directly._\n\n| ID      | Name                                   | Supported |\n|---------|----------------------------------------|-----------|\n| 0       | (Spare/Reserved)                       | -         |\n| 1       | Cause                                  | Yes       |\n| 2       | IMSI                                   | Yes       |\n| 3       | Routeing Area Identity (RAI)           | Yes       |\n| 4       | Temporary Logical Link Identity (TLLI) | Yes       |\n| 5       | Packet TMSI (P-TMSI)                   | Yes       |\n| 6       | Quality of Service (QoS) Profile       | Yes       |\n| 7       | (Spare/Reserved)                       | -         |\n| 8       | Reordering Required                    | Yes       |\n| 9       | Authentication Triplet                 |           |\n| 10      | (Spare/Reserved)                       | -         |\n| 11      | MAP Cause                              |           |\n| 12      | P-TMSI Signature                       | Yes       |\n| 13      | MS Validated                           |           |\n| 14      | Recovery                               | Yes       |\n| 15      | Selection mode                         | Yes       |\n| 16      | Flow Label Data I                      | Yes       |\n| 17      | Flow Label Signalling                  | Yes       |\n| 18      | Flow Label Data II                     | Yes       |\n| 19      | MS Not Reachable Reason                | Yes       |\n| 20-126  | (Spare/Reserved)                       | -         |\n| 127     | Charging ID                            | Yes       |\n| 128     | End User Address                       | Yes       |\n| 129     | MM Context                             |           |\n| 130     | PDP Context                            |           |\n| 131     | Access Point Name                      | Yes       |\n| 132     | Protocol Configuration Options         |           |\n| 133     | GSN Address                            | Yes       |\n| 134     | MSISDN                                 | Yes       |\n| 135-250 | (Spare/Reserved)                       | -         |\n| 251     | Charging Gateway Address               | Yes       |\n| 252-254 | (Spare/Reserved)                       | -         |\n| 255     | Private Extension                      | Yes       |\n"
  },
  {
    "path": "gtpv0/constants.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv0\n\n// Cause definitions.\nconst (\n\tCauseRequestIMSI              uint8 = 0\n\tCauseRequestIMEI              uint8 = 1\n\tCauseRequestIMSIandIMEI       uint8 = 2\n\tCauseNoIdentityNeeded         uint8 = 3\n\tCauseRequestAccepted          uint8 = 128\n\tCauseNonExistent              uint8 = 192\n\tCauseInvalidMessageFormat     uint8 = 193\n\tCauseIMSINotKnown             uint8 = 194\n\tCauseMSIsGPRSDetached         uint8 = 195\n\tCauseMSIsNotGPRSResponding    uint8 = 196\n\tCauseMSRefuses                uint8 = 197\n\tCauseVersionNotSupported      uint8 = 198\n\tCauseNoResourcesAvailable     uint8 = 199\n\tCauseServiceNotSupported      uint8 = 200\n\tCauseMandatoryIEIncorrect     uint8 = 201\n\tCauseMandatoryIEMissing       uint8 = 202\n\tCauseOptionalIEIncorrect      uint8 = 203\n\tCauseSystemFailure            uint8 = 204\n\tCauseRoamingRestriction       uint8 = 205\n\tCausePTMSISignatureMismatch   uint8 = 206\n\tCauseGPRSConnectionSuspended  uint8 = 207\n\tCauseAuthenticationFailure    uint8 = 208\n\tCauseUserAuthenticationFailed uint8 = 209\n)\n\n// PDP Type Organization definitions.\nconst (\n\tPDPTypeETSI uint8 = iota | 0xf0\n\tPDPTypeIETF\n)\n\n// SelectionMode definitions.\nconst (\n\tSelectionModeMSorNetworkProvidedAPNSubscribedVerified uint8 = iota | 0xf0\n\tSelectionModeMSProvidedAPNSubscriptionNotVerified\n\tSelectionModeNetworkProvidedAPNSubscriptionNotVerified\n)\n"
  },
  {
    "path": "gtpv0/doc.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package gtpv0 provides simple and painless handling of GTPv0 protocol in pure Golang.\n//\n// This package is still under construction. The networking feature would be available in the future.\n// Please see README.md for detailed usage of the APIs provided by this package.\n//\n// https://github.com/wmnsk/go-gtp/blob/main/gtpv0/README.md\npackage gtpv0\n"
  },
  {
    "path": "gtpv0/ie/apn.go",
    "content": "// Copyright 2019-2024 go-gtp. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"strings\"\n)\n\n// NewAccessPointName creates a new AccessPointName IE.\nfunc NewAccessPointName(apn string) *IE {\n\ti := New(AccessPointName, make([]byte, len(apn)+1))\n\tvar offset = 0\n\tfor _, label := range strings.Split(apn, \".\") {\n\t\tl := len(label)\n\t\ti.Payload[offset] = uint8(l)\n\t\tcopy(i.Payload[offset+1:], label)\n\t\toffset += l + 1\n\t}\n\n\treturn i\n}\n\n// AccessPointName returns AccessPointName in string if type of IE matches.\nfunc (i *IE) AccessPointName() (string, error) {\n\tif i.Type != AccessPointName {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tvar (\n\t\tapn    []string\n\t\toffset int\n\t)\n\n\tmax := len(i.Payload)\n\tfor {\n\t\tif offset >= max {\n\t\t\tbreak\n\t\t}\n\t\tl := int(i.Payload[offset])\n\t\tif offset+l+1 >= max {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\tapn = append(apn, string(i.Payload[offset+1:offset+l+1]))\n\t\toffset += l + 1\n\t}\n\n\treturn strings.Join(apn, \".\"), nil\n}\n\n// MustAccessPointName returns AccessPointName in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAccessPointName() string {\n\tv, _ := i.AccessPointName()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/cause.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewCause creates a new Cause IE.\nfunc NewCause(cause uint8) *IE {\n\treturn newUint8ValIE(Cause, cause)\n}\n\n// Cause returns Cause value if type matches.\nfunc (i *IE) Cause() (uint8, error) {\n\tif i.Type != Cause {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustCause returns Cause in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCause() uint8 {\n\tv, _ := i.Cause()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/charging-gateway-address.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// NewChargingGatewayAddress creates a new ChargingGatewayAddress IE from string.\nfunc NewChargingGatewayAddress(addr string) *IE {\n\tip := net.ParseIP(addr)\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn New(ChargingGatewayAddress, v4)\n\t}\n\t// IPv6\n\treturn New(ChargingGatewayAddress, ip)\n}\n\n// ChargingGatewayAddress returns ChargingGatewayAddress value if type matches.\nfunc (i *IE) ChargingGatewayAddress() (string, error) {\n\tif i.Type != ChargingGatewayAddress {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn net.IP(i.Payload).String(), nil\n}\n\n// MustChargingGatewayAddress returns ChargingGatewayAddress in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustChargingGatewayAddress() string {\n\tv, _ := i.ChargingGatewayAddress()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/charging-id.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewChargingID creates a new ChargingID IE.\nfunc NewChargingID(id uint32) *IE {\n\treturn newUint32ValIE(ChargingID, id)\n}\n\n// ChargingID returns ChargingID value in uint32 if type matches.\nfunc (i *IE) ChargingID() (uint32, error) {\n\tif i.Type != ChargingID {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload), nil\n}\n\n// MustChargingID returns ChargingID in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustChargingID() uint32 {\n\tv, _ := i.ChargingID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/end-user-address.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// PDP Type Organization definitions.\nconst (\n\tpdpTypeETSI uint8 = iota | 0xf0\n\tpdpTypeIETF\n)\n\n// NewEndUserAddress creates a new EndUserAddress IE from the given IP Address in string.\n//\n// The addr can be either IPv4 or IPv6. If the address type is PPP,\n// just put \"ppp\" in addr parameter or use NewEndUserAddressPPP func instead.\nfunc NewEndUserAddress(addr string) *IE {\n\tif addr == \"ppp\" {\n\t\treturn NewEndUserAddressPPP()\n\t}\n\tip := net.ParseIP(addr)\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn newEUAddrV4(v4)\n\t}\n\n\treturn newEUAddrV6(ip)\n}\n\n// NewEndUserAddressIPv4 creates a new EndUserAddress IE with IPv4.\nfunc NewEndUserAddressIPv4(addr string) *IE {\n\tv4 := net.ParseIP(addr).To4()\n\tif v4 == nil {\n\t\treturn New(EndUserAddress, []byte{0xf1, 0x21})\n\t}\n\n\treturn newEUAddrV4(v4)\n}\n\n// NewEndUserAddressIPv6 creates a new EndUserAddress IE with IPv6.\nfunc NewEndUserAddressIPv6(addr string) *IE {\n\tv6 := net.ParseIP(addr).To16()\n\tif v6 == nil {\n\t\treturn New(EndUserAddress, []byte{0xf1, 0x57})\n\t}\n\n\treturn newEUAddrV6(v6)\n}\n\nfunc newEUAddrV4(v4 []byte) *IE {\n\te := New(\n\t\tEndUserAddress,\n\t\tmake([]byte, 6),\n\t)\n\te.Payload[0] = pdpTypeIETF\n\te.Payload[1] = 0x21\n\tcopy(e.Payload[2:], v4)\n\n\treturn e\n}\n\nfunc newEUAddrV6(v6 []byte) *IE {\n\te := New(\n\t\tEndUserAddress,\n\t\tmake([]byte, 18),\n\t)\n\te.Payload = make([]byte, 18)\n\te.Payload[0] = pdpTypeIETF\n\te.Payload[1] = 0x57\n\tcopy(e.Payload[2:], v6)\n\n\treturn e\n}\n\n// NewEndUserAddressPPP creates a new EndUserAddress IE with PPP.\nfunc NewEndUserAddressPPP() *IE {\n\te := New(EndUserAddress, make([]byte, 2))\n\te.Payload[0] = pdpTypeETSI\n\te.Payload[1] = pdpTypeIETF\n\n\te.SetLength()\n\treturn e\n}\n\n// EndUserAddress returns EndUserAddress value if type matches.\nfunc (i *IE) EndUserAddress() ([]byte, error) {\n\tif i.Type != EndUserAddress {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustEndUserAddress returns EndUserAddress in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustEndUserAddress() []byte {\n\tv, _ := i.EndUserAddress()\n\treturn v\n}\n\n// PDPTypeOrganization returns PDPTypeOrganization if type matches.\nfunc (i *IE) PDPTypeOrganization() (uint8, error) {\n\tif i.Type != EndUserAddress {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustPDPTypeOrganization returns PDPTypeOrganization in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPDPTypeOrganization() uint8 {\n\tv, _ := i.PDPTypeOrganization()\n\treturn v\n}\n\n// PDPTypeNumber returns PDPTypeNumber if type matches.\nfunc (i *IE) PDPTypeNumber() (uint8, error) {\n\tif i.Type != EndUserAddress {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[1], nil\n}\n\n// MustPDPTypeNumber returns PDPTypeNumber in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPDPTypeNumber() uint8 {\n\tv, _ := i.PDPTypeNumber()\n\treturn v\n}\n\n// IPAddress returns IPAddress if type matches.\nfunc (i *IE) IPAddress() (string, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase EndUserAddress:\n\t\tif i.MustPDPTypeOrganization() != pdpTypeIETF {\n\t\t\treturn \"\", ErrMalformed\n\t\t}\n\t\tif len(i.Payload) < 3 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn net.IP(i.Payload[2:]).String(), nil\n\tcase GSNAddress:\n\t\treturn net.IP(i.Payload).String(), nil\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustIPAddress returns IPAddress in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIPAddress() string {\n\tv, _ := i.IPAddress()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Error definitions.\nvar (\n\tErrInvalidLength     = errors.New(\"got invalid length\")\n\tErrTooShortToMarshal = errors.New(\"too short to Marshal\")\n\tErrTooShortToParse   = errors.New(\"too short to Parse as GTPv0 IE\")\n\n\tErrMalformed = errors.New(\"malformed IE\")\n)\n\n// InvalidTypeError indicates the type of IE is invalid.\ntype InvalidTypeError struct {\n\tType uint8\n}\n\n// Error returns message with the invalid type given.\nfunc (e *InvalidTypeError) Error() string {\n\treturn fmt.Sprintf(\"got invalid type: %v\", e.Type)\n}\n"
  },
  {
    "path": "gtpv0/ie/flow-label.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewFlowLabelDataI creates a new FlowLabelDataI IE.\nfunc NewFlowLabelDataI(label uint16) *IE {\n\treturn newUint16ValIE(FlowLabelDataI, label)\n}\n\n// FlowLabelDataI returns FlowLabelDataI if type matches.\nfunc (i *IE) FlowLabelDataI() (uint16, error) {\n\tif i.Type != FlowLabelDataI {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(i.Payload), nil\n}\n\n// MustFlowLabelDataI returns FlowLabelDataI in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustFlowLabelDataI() uint16 {\n\tv, _ := i.FlowLabelDataI()\n\treturn v\n}\n\n// NewFlowLabelSignalling creates a new FlowLabelSignalling IE.\nfunc NewFlowLabelSignalling(label uint16) *IE {\n\treturn newUint16ValIE(FlowLabelSignalling, label)\n}\n\n// FlowLabelSignalling returns FlowLabelSignalling if type matches.\nfunc (i *IE) FlowLabelSignalling() (uint16, error) {\n\tif i.Type != FlowLabelSignalling {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(i.Payload), nil\n}\n\n// MustFlowLabelSignalling returns FlowLabelSignalling in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustFlowLabelSignalling() uint16 {\n\tv, _ := i.FlowLabelSignalling()\n\treturn v\n}\n\n// NewFlowLabelDataII creates a new FlowLabelDataII IE.\nfunc NewFlowLabelDataII(nsapi uint8, label uint16) *IE {\n\ti := New(FlowLabelDataII, make([]byte, 3))\n\ti.Payload[0] = nsapi | 0xf0\n\tbinary.BigEndian.PutUint16(i.Payload[1:3], label)\n\treturn i\n}\n\n// FlowLabelDataII returns FlowLabelDataII if type matches.\nfunc (i *IE) FlowLabelDataII() ([]byte, error) {\n\tif i.Type != FlowLabelDataII {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustFlowLabelDataII returns FlowLabelDataII in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustFlowLabelDataII() []byte {\n\tv, _ := i.FlowLabelDataII()\n\treturn v\n}\n\n// NSAPI returns NSAPI in uint8 if type matches.\nfunc (i *IE) NSAPI() (uint8, error) {\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase FlowLabelDataII:\n\t\treturn i.Payload[0] & 0x0f, nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustNSAPI returns NSAPI in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustNSAPI() uint8 {\n\tv, _ := i.NSAPI()\n\treturn v\n}\n\n// FlowLabelData returns FlowLabelData in uint16 if type matches.\nfunc (i *IE) FlowLabelData() (uint16, error) {\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase FlowLabelDataI:\n\t\treturn i.FlowLabelDataI()\n\tcase FlowLabelSignalling:\n\t\treturn i.FlowLabelSignalling()\n\tcase FlowLabelDataII:\n\t\tif len(i.Payload) < 3 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[1:3]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustFlowLabelData returns FlowLabelData in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustFlowLabelData() uint16 {\n\tv, _ := i.FlowLabelData()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/gsn-address.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// NewGSNAddress creates a new GSNAddress IE from string.\nfunc NewGSNAddress(addr string) *IE {\n\tip := net.ParseIP(addr)\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn New(GSNAddress, v4)\n\t}\n\t// IPv6\n\treturn New(GSNAddress, ip)\n}\n\n// GSNAddress returns GSNAddress value if type matches.\nfunc (i *IE) GSNAddress() (string, error) {\n\tif i.Type != GSNAddress {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn net.IP(i.Payload).String(), nil\n}\n\n// MustGSNAddress returns GSNAddress in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustGSNAddress() string {\n\tv, _ := i.GSNAddress()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/ie.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n/*\nPackage ie provides encoding/decoding feature of GTPv0 Information Elements.\n*/\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n)\n\n// TV IE definitions.\nconst (\n\tCause                        uint8 = 1\n\tIMSI                         uint8 = 2\n\tRouteingAreaIdentity         uint8 = 3\n\tTemporaryLogicalLinkIdentity uint8 = 4\n\tPacketTMSI                   uint8 = 5\n\tQualityOfServiceProfile      uint8 = 6\n\tReorderingRequired           uint8 = 8\n\tAuthenticationTriplet        uint8 = 9\n\tMAPCause                     uint8 = 11\n\tPTMSISignature               uint8 = 12\n\tMSValidated                  uint8 = 13\n\tRecovery                     uint8 = 14\n\tSelectionMode                uint8 = 15\n\tFlowLabelDataI               uint8 = 16\n\tFlowLabelSignalling          uint8 = 17\n\tFlowLabelDataII              uint8 = 18\n\tMSNotReachableReason         uint8 = 19\n\tChargingID                   uint8 = 127\n)\n\n// TLV IE definitions.\nconst (\n\tEndUserAddress               uint8 = 128\n\tMMContext                    uint8 = 129\n\tPDPContext                   uint8 = 130\n\tAccessPointName              uint8 = 131\n\tProtocolConfigurationOptions uint8 = 132\n\tGSNAddress                   uint8 = 133\n\tMSISDN                       uint8 = 134\n\tChargingGatewayAddress       uint8 = 251\n\tPrivateExtension             uint8 = 255\n)\n\n// IE is a GTPv0 Information Element.\ntype IE struct {\n\tType    uint8\n\tLength  uint16\n\tPayload []byte\n}\n\n// New creates new IE.\nfunc New(t uint8, p []byte) *IE {\n\ti := &IE{Type: t, Payload: p}\n\ti.SetLength()\n\treturn i\n}\n\n// Marshal returns the byte sequence generated from an IE instance.\nfunc (i *IE) Marshal() ([]byte, error) {\n\tb := make([]byte, i.MarshalLen())\n\tif err := i.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (i *IE) MarshalTo(b []byte) error {\n\tif len(b) < i.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tvar offset = 1\n\tb[0] = i.Type\n\tif !i.IsTV() {\n\t\tbinary.BigEndian.PutUint16(b[1:3], i.Length)\n\t\toffset += 2\n\t}\n\tcopy(b[offset:i.MarshalLen()], i.Payload)\n\treturn nil\n}\n\n// Parse Parses given byte sequence as a GTPv0 Information Element.\nfunc Parse(b []byte) (*IE, error) {\n\ti := &IE{}\n\tif err := i.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn i, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in GTPv0 IE.\nfunc (i *IE) UnmarshalBinary(b []byte) error {\n\tif len(b) < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\ti.Type = b[0]\n\tif i.IsTV() {\n\t\treturn parseTVFromBytes(i, b)\n\t}\n\treturn parseTLVFromBytes(i, b)\n}\n\nfunc parseTVFromBytes(i *IE, b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\tif i.MarshalLen() > l {\n\t\treturn ErrInvalidLength\n\t}\n\ti.Length = 0\n\ti.Payload = b[1:i.MarshalLen()]\n\n\treturn nil\n}\n\nfunc parseTLVFromBytes(i *IE, b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\ti.Length = binary.BigEndian.Uint16(b[1:3])\n\tif int(i.Length)+3 > l {\n\t\treturn ErrInvalidLength\n\t}\n\n\ti.Payload = b[3 : 3+int(i.Length)]\n\treturn nil\n}\n\nvar tvLengthMap = map[uint8]int{\n\t0:   0,  // Reserved\n\t1:   1,  // Cause\n\t2:   8,  // IMSI\n\t3:   6,  // RAI\n\t4:   4,  // TLLI\n\t5:   4,  // P-TMSI\n\t6:   3,  // QoS\n\t8:   1,  // Reordering Required\n\t9:   28, // Authentication Triplet\n\t11:  1,  // MAP Cause\n\t12:  3,  // P-TMSI Signature\n\t13:  1,  // MS Validated\n\t14:  1,  // Recovery\n\t15:  1,  // Selection Mode\n\t16:  2,  // Flow Label Data I\n\t17:  2,  // Flow Label Signalling\n\t18:  3,  // Flow Label Data II\n\t19:  1,  // MS Not Reachable Reason\n\t127: 4,  // Charging ID\n}\n\n// IsTV checks if a IE is TV format. If false, it indicates the IE has Length inside.\nfunc (i *IE) IsTV() bool {\n\treturn int(i.Type) < 0x80\n}\n\n// MarshalLen returns the serial length of IE.\nfunc (i *IE) MarshalLen() int {\n\tif l, ok := tvLengthMap[i.Type]; ok {\n\t\treturn l + 1\n\t}\n\tif i.Type < 128 {\n\t\treturn 1 + len(i.Payload)\n\t}\n\treturn 3 + len(i.Payload)\n}\n\n// SetLength sets the length in Length field.\nfunc (i *IE) SetLength() {\n\tif _, ok := tvLengthMap[i.Type]; ok {\n\t\ti.Length = 0\n\t\treturn\n\t}\n\n\ti.Length = uint16(len(i.Payload))\n}\n\n// Name returns the name of IE in string.\nfunc (i *IE) Name() string {\n\tif n, ok := ieTypeNameMap[i.Type]; ok {\n\t\treturn n\n\t}\n\treturn \"Undefined\"\n}\n\n// String returns the GTPv0 IE values in human readable format.\nfunc (i *IE) String() string {\n\tif i == nil {\n\t\treturn \"nil\"\n\t}\n\treturn fmt.Sprintf(\"{%s: {Type: %d, Length: %d, Payload: %#v}}\",\n\t\ti.Name(),\n\t\ti.Type,\n\t\ti.Length,\n\t\ti.Payload,\n\t)\n}\n\n// ParseMultiIEs Parses multiple (unspecified number of) IEs to []*IE at a time.\nfunc ParseMultiIEs(b []byte) ([]*IE, error) {\n\tvar ies []*IE\n\tfor {\n\t\tif len(b) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\ti, err := Parse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\ties = append(ies, i)\n\t\tb = b[i.MarshalLen():]\n\t\tcontinue\n\t}\n\treturn ies, nil\n}\n\nfunc newUint8ValIE(t, v uint8) *IE {\n\treturn New(t, []byte{v})\n}\n\nfunc newUint16ValIE(t uint8, v uint16) *IE {\n\ti := New(t, make([]byte, 2))\n\tbinary.BigEndian.PutUint16(i.Payload, v)\n\treturn i\n}\n\nfunc newUint32ValIE(t uint8, v uint32) *IE {\n\ti := New(t, make([]byte, 4))\n\tbinary.BigEndian.PutUint32(i.Payload, v)\n\treturn i\n}\n\n// left for future use.\n// func newStringIE(t uint8, str string) *IE {\n// \treturn New(t, []byte(str))\n// }\n\nvar ieTypeNameMap = map[uint8]string{\n\t1:   \"Cause\",\n\t2:   \"IMSI\",\n\t3:   \"RouteingAreaIdentity\",\n\t4:   \"TemporaryLogicalLinkIdentity\",\n\t5:   \"PacketTMSI\",\n\t6:   \"QualityOfServiceProfile\",\n\t8:   \"ReorderingRequired\",\n\t9:   \"AuthenticationTriplet\",\n\t11:  \"MAPCause\",\n\t12:  \"PTMSISignature\",\n\t13:  \"MSValidated\",\n\t14:  \"Recovery\",\n\t15:  \"SelectionMode\",\n\t16:  \"FlowLabelDataI\",\n\t17:  \"FlowLabelSignalling\",\n\t18:  \"FlowLabelDataII\",\n\t19:  \"MSNotReachableReason\",\n\t127: \"ChargingID\",\n\t128: \"EndUserAddress\",\n\t129: \"MMContext\",\n\t130: \"PDPContext\",\n\t131: \"AccessPointName\",\n\t132: \"ProtocolConfigurationOptions\",\n\t133: \"GSNAddress\",\n\t134: \"MSISDN\",\n\t251: \"ChargingGatewayAddress\",\n\t255: \"PrivateExtension\",\n}\n"
  },
  {
    "path": "gtpv0/ie/ie_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"log\"\n\n// Serialize serializes IE into bytes.\n//\n// Deprecated: use IE.Marshal instead.\nfunc (i *IE) Serialize() ([]byte, error) {\n\tlog.Println(\"IE.Serialize is deprecated. use IE.Marshal instead\")\n\treturn i.Marshal()\n}\n\n// SerializeTo serializes IE into bytes given as b.\n//\n// Deprecated: use IE.MarshalTo instead.\nfunc (i *IE) SerializeTo(b []byte) error {\n\tlog.Println(\"IE.SerializeTo is deprecated. use IE.MarshalTo instead\")\n\treturn i.MarshalTo(b)\n}\n\n// Decode decodes bytes as IE.\n//\n// Deprecated: use Parse instead.\nfunc Decode(b []byte) (*IE, error) {\n\tlog.Println(\"Decode is deprecated. use Parse instead\")\n\treturn Parse(b)\n}\n\n// DecodeFromBytes decodes bytes as IE.\n//\n// Deprecated: use IE.UnmarshalBinary instead.\nfunc (i *IE) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"IE.DecodeFromBytes is deprecated. use IE.UnmarshalBinary instead\")\n\treturn i.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of IE.\n//\n// Deprecated: use IE.MarshalLen instead.\nfunc (i *IE) Len() int {\n\tlog.Println(\"IE.Len is deprecated. use IE.MarshalLen instead\")\n\treturn i.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/ie/ie_fuzz_test.go",
    "content": "package ie_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := ie.Parse(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv0/ie/ie_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/gtpv0\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\nfunc TestIE(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  *ie.IE\n\t\tSerialized  []byte\n\t}{\n\t\t{\n\t\t\t\"Cause\",\n\t\t\tie.NewCause(gtpv0.CauseRequestAccepted),\n\t\t\t[]byte{0x01, 0x80},\n\t\t}, {\n\t\t\t\"IMSI\",\n\t\t\tie.NewIMSI(\"123450123456789\"),\n\t\t\t[]byte{0x02, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9},\n\t\t}, {\n\t\t\t\"RAI\",\n\t\t\tie.NewRouteingAreaIdentity(\"123\", \"45\", 0x1111, 0x22),\n\t\t\t[]byte{0x03, 0x21, 0xf3, 0x54, 0x11, 0x11, 0x22},\n\t\t}, {\n\t\t\t\"TLLI\",\n\t\t\tie.NewTemporaryLogicalLinkIdentity(0xff00ff00),\n\t\t\t[]byte{0x04, 0xff, 0x00, 0xff, 0x00},\n\t\t}, {\n\t\t\t\"PacketTMSI\",\n\t\t\tie.NewPacketTMSI(0xdeadbeef),\n\t\t\t[]byte{0x05, 0xde, 0xad, 0xbe, 0xef},\n\t\t}, { // XXX - not implemented fully\n\t\t\t\"QoS Profile\",\n\t\t\tie.NewQualityOfServiceProfile(1, 1, 1, 1, 1),\n\t\t\t[]byte{0x06, 0x09, 0x11, 0x01},\n\t\t}, {\n\t\t\t\"ReorderingRequired\",\n\t\t\tie.NewReorderingRequired(false),\n\t\t\t[]byte{0x08, 0xfe},\n\t\t},\n\t\t/* XXX - not implemented\n\t\t{\n\t\t\t\"AuthenticationTriplet\",\n\t\t\tie.NewAuthenticationTriplet(),\n\t\t\t[]byte{},\n\t\t}, {\n\t\t\t\"MAPCause\",\n\t\t\tie.NewMAPCause(),\n\t\t\t[]byte{},\n\t\t}, {\n\t\t\t\"PacketTMSISignature\",\n\t\t\tie.NewPacketTMSISignature(),\n\t\t\t[]byte{},\n\t\t}, {\n\t\t\t\"MSValidated\",\n\t\t\tie.NewMSValidated(),\n\t\t\t[]byte{},\n\t\t},*/\n\t\t{\n\t\t\t\"PTMSISignature\",\n\t\t\tie.NewPTMSISignature(0xbeebee),\n\t\t\t[]byte{0x0c, 0xbe, 0xeb, 0xee},\n\t\t}, {\n\t\t\t\"Recovery\",\n\t\t\tie.NewRecovery(0x80),\n\t\t\t[]byte{0x0e, 0x80},\n\t\t}, {\n\t\t\t\"SelectionMode\",\n\t\t\tie.NewSelectionMode(0xff),\n\t\t\t[]byte{0x0f, 0xff},\n\t\t}, {\n\t\t\t\"FlowLabelDataI\",\n\t\t\tie.NewFlowLabelDataI(0x0001),\n\t\t\t[]byte{0x10, 0x00, 0x01},\n\t\t}, {\n\t\t\t\"FlowLabelSignalling\",\n\t\t\tie.NewFlowLabelSignalling(0x0001),\n\t\t\t[]byte{0x11, 0x00, 0x01},\n\t\t}, {\n\t\t\t\"FlowLabelDataII\",\n\t\t\tie.NewFlowLabelDataII(5, 0x0001),\n\t\t\t[]byte{0x12, 0xf5, 0x00, 0x01},\n\t\t}, {\n\t\t\t\"MSNotReachableReason\",\n\t\t\tie.NewMSNotReachableReason(0xff),\n\t\t\t[]byte{0x13, 0xff},\n\t\t}, {\n\t\t\t\"ChargingID\",\n\t\t\tie.NewChargingID(0xff00ff00),\n\t\t\t[]byte{0x7f, 0xff, 0x00, 0xff, 0x00},\n\t\t}, {\n\t\t\t\"EndUserAddress/v4\",\n\t\t\tie.NewEndUserAddressIPv4(\"1.1.1.1\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x80, 0x00, 0x06,\n\t\t\t\t// Value\n\t\t\t\t0xf1, 0x21, 0x01, 0x01, 0x01, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"EndUserAddress/v6\",\n\t\t\tie.NewEndUserAddressIPv6(\"2001::1\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x80, 0x00, 0x12,\n\t\t\t\t// Value\n\t\t\t\t0xf1, 0x57, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"EndUserAddress/ppp\",\n\t\t\tie.NewEndUserAddressPPP(),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x80, 0x00, 0x02,\n\t\t\t\t// Value\n\t\t\t\t0xf0, 0xf1,\n\t\t\t},\n\t\t},\n\t\t/* XXX - not implemented\n\t\t{\n\t\t\t\"MMContext\",\n\t\t\tie.NewMMContext(),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x81, 0x00, 0x00,\n\t\t\t\t// Value\n\t\t\t},\n\t\t}, {\n\t\t\t\"PDPContext\",\n\t\t\tie.NewPDPContext(),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x81, 0x00, 0x00,\n\t\t\t\t// Value\n\t\t\t},\n\t\t},\n\t\t*/\n\t\t{\n\t\t\t\"AccessPointName\",\n\t\t\tie.NewAccessPointName(\"some.apn.example\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x83, 0x00, 0x11,\n\t\t\t\t// Value\n\t\t\t\t0x04, 0x73, 0x6f, 0x6d, 0x65, 0x03, 0x61, 0x70, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,\n\t\t\t},\n\t\t},\n\t\t/* XXX - not implemented\n\t\t{\n\t\t\t\"PCO\",\n\t\t\tie.NewProtocolConfigurationOption(),\n\t\t\t[]byte{},\n\t\t}, */\n\t\t{\n\t\t\t\"GSNAddress/v4\",\n\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x85, 0x00, 0x04,\n\t\t\t\t// Value\n\t\t\t\t0x01, 0x01, 0x01, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"GSNAddress/v6\",\n\t\t\tie.NewGSNAddress(\"2001::1\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x85, 0x00, 0x10,\n\t\t\t\t// Value\n\t\t\t\t0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"MSISDN\",\n\t\t\tie.NewMSISDN(\"819012345678\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0x86, 0x00, 0x07,\n\t\t\t\t// Value\n\t\t\t\t0x91, 0x18, 0x09, 0x21, 0x43, 0x65, 0x87,\n\t\t\t},\n\t\t}, {\n\t\t\t\"ChargingGatewayAddress/v4\",\n\t\t\tie.NewChargingGatewayAddress(\"1.1.1.1\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0xfb, 0x00, 0x04,\n\t\t\t\t// Value\n\t\t\t\t0x01, 0x01, 0x01, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"ChargingGatewayAddress/v6\",\n\t\t\tie.NewChargingGatewayAddress(\"2001::1\"),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0xfb, 0x00, 0x10,\n\t\t\t\t// Value\n\t\t\t\t0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"PrivateExtension\",\n\t\t\tie.NewPrivateExtension(0x0080, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0xff, 0x00, 0x06,\n\t\t\t\t// Value\n\t\t\t\t0x00, 0x80, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"Marshal/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.Serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"Parse/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.Parse(c.Serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.structured); diff != \"\" {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv0/ie/imsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewIMSI creates a new IMSI IE.\nfunc NewIMSI(imsi string) *IE {\n\ti, err := utils.StrToSwappedBytes(imsi, \"f\")\n\tif err != nil {\n\t\treturn New(IMSI, nil)\n\t}\n\treturn New(IMSI, i)\n}\n\n// IMSI returns IMSI value in string if type matches.\nfunc (i *IE) IMSI() (string, error) {\n\tif i.Type != IMSI {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.SwappedBytesToStr(i.Payload, true), nil\n}\n\n// MustIMSI returns IMSI in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIMSI() string {\n\tv, _ := i.IMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/ms-not-reachable-reason.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewMSNotReachableReason creates a new MSNotReachableReason IE.\nfunc NewMSNotReachableReason(reason uint8) *IE {\n\treturn newUint8ValIE(MSNotReachableReason, reason)\n}\n\n// MSNotReachableReason returns MSNotReachableReason value if type matches.\nfunc (i *IE) MSNotReachableReason() (uint8, error) {\n\tif i.Type != MSNotReachableReason {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustMSNotReachableReason returns MSNotReachableReason in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMSNotReachableReason() uint8 {\n\tv, _ := i.MSNotReachableReason()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/msisdn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewMSISDN creates a new MSISDN IE.\nfunc NewMSISDN(msisdn string) *IE {\n\ti, err := utils.StrToSwappedBytes(\"19\"+msisdn, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn New(MSISDN, i)\n}\n\n// MSISDN returns MSISDN value if type matches.\nfunc (i *IE) MSISDN() (string, error) {\n\tif i.Type != MSISDN {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.SwappedBytesToStr(i.Payload[1:], false), nil\n}\n\n// MustMSISDN returns MSISDN in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMSISDN() string {\n\tv, _ := i.MSISDN()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/p-tmsi-signature.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewPTMSISignature creates a new PTMSISignature IE.\nfunc NewPTMSISignature(sig uint32) *IE {\n\treturn New(PTMSISignature, utils.Uint32To24(sig))\n}\n\n// PTMSISignature returns PTMSISignature value in uint32 if type matches.\nfunc (i *IE) PTMSISignature() (uint32, error) {\n\tif i.Type != PTMSISignature {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.Uint24To32(i.Payload), nil\n}\n\n// MustPTMSISignature returns PTMSISignature in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPTMSISignature() uint32 {\n\tv, _ := i.PTMSISignature()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/p-tmsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewPacketTMSI creates a new PacketTMSI IE.\nfunc NewPacketTMSI(ptmsi uint32) *IE {\n\treturn newUint32ValIE(PacketTMSI, ptmsi)\n}\n\n// PacketTMSI returns PacketTMSI value in uint32 if type matches.\nfunc (i *IE) PacketTMSI() (uint32, error) {\n\tif i.Type != PacketTMSI {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload), nil\n}\n\n// MustPacketTMSI returns PacketTMSI in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPacketTMSI() uint32 {\n\tv, _ := i.PacketTMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/private-extension.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewPrivateExtension creates a new PrivateExtension IE from string.\nfunc NewPrivateExtension(id uint16, val []byte) *IE {\n\ti := New(PrivateExtension, make([]byte, 2+len(val)))\n\tbinary.BigEndian.PutUint16(i.Payload[:2], id)\n\tcopy(i.Payload[2:], val)\n\treturn i\n}\n\n// PrivateExtension returns PrivateExtension value if type matches.\nfunc (i *IE) PrivateExtension() ([]byte, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustPrivateExtension returns PrivateExtension in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPrivateExtension() []byte {\n\tv, _ := i.PrivateExtension()\n\treturn v\n}\n\n// ExtensionIdentifier returns ExtensionIdentifier value in uint16 if type matches.\nfunc (i *IE) ExtensionIdentifier() (uint16, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(i.Payload[:2]), nil\n}\n\n// MustExtensionIdentifier returns ExtensionIdentifier in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtensionIdentifier() uint16 {\n\tv, _ := i.ExtensionIdentifier()\n\treturn v\n}\n\n// ExtensionValue returns ExtensionValue value if type matches.\nfunc (i *IE) ExtensionValue() ([]byte, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[2:], nil\n}\n\n// MustExtensionValue returns ExtensionValue in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtensionValue() []byte {\n\tv, _ := i.ExtensionValue()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/qos-profile.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewQualityOfServiceProfile creates a new QualityOfServiceProfile IE.\nfunc NewQualityOfServiceProfile(delay, reliability, peak, precedence, mean uint8) *IE {\n\ti := New(QualityOfServiceProfile, make([]byte, 3))\n\ti.Payload[0] = ((delay & 0x07) << 3) | (reliability & 0x07)\n\ti.Payload[1] = ((peak & 0x0f) << 4) | (precedence & 0x07)\n\ti.Payload[2] = mean & 0x1f\n\n\treturn i\n}\n\n// QualityOfServiceProfile returns QualityOfServiceProfile if type matches.\nfunc (i *IE) QualityOfServiceProfile() ([]byte, error) {\n\tif i.Type != QualityOfServiceProfile {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustQualityOfServiceProfile returns QualityOfServiceProfile in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQualityOfServiceProfile() []byte {\n\tv, _ := i.QualityOfServiceProfile()\n\treturn v\n}\n\n// QoSDelay returns QoS Delay value in uint8 if type matches.\nfunc (i *IE) QoSDelay() (uint8, error) {\n\tif i.Type != QualityOfServiceProfile {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0] & 0x38, nil\n}\n\n// MustQoSDelay returns QoSDelay in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQoSDelay() uint8 {\n\tv, _ := i.QoSDelay()\n\treturn v\n}\n\n// QoSReliability returns QoS Reliability value in uint8 if type matches.\nfunc (i *IE) QoSReliability() (uint8, error) {\n\tif i.Type != QualityOfServiceProfile {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0] & 0x07, nil\n}\n\n// MustQoSReliability returns QoSReliability in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQoSReliability() uint8 {\n\tv, _ := i.QoSReliability()\n\treturn v\n}\n\n// QoSPeak returns QoS Peak value in uint8 if type matches.\nfunc (i *IE) QoSPeak() (uint8, error) {\n\tif i.Type != QualityOfServiceProfile {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[1] & 0xf0, nil\n}\n\n// MustQoSPeak returns QoSPeak in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQoSPeak() uint8 {\n\tv, _ := i.QoSPeak()\n\treturn v\n}\n\n// QoSPrecedence returns QoS Precedence value in uint8 if type matches.\nfunc (i *IE) QoSPrecedence() (uint8, error) {\n\tif i.Type != QualityOfServiceProfile {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[1] & 0x07, nil\n}\n\n// MustQoSPrecedence returns QoSPrecedence in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQoSPrecedence() uint8 {\n\tv, _ := i.QoSPrecedence()\n\treturn v\n}\n\n// QoSMean returns QoS Mean value in uint8 if type matches.\nfunc (i *IE) QoSMean() (uint8, error) {\n\tif i.Type != QualityOfServiceProfile {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[2] & 0x0f, nil\n}\n\n// MustQoSMean returns QoSMean in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQoSMean() uint8 {\n\tv, _ := i.QoSMean()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/rai.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewRouteingAreaIdentity creates a new RouteingAreaIdentity IE.\nfunc NewRouteingAreaIdentity(mcc, mnc string, lac uint16, rac uint8) *IE {\n\tplmn, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\trai := New(\n\t\tRouteingAreaIdentity,\n\t\tmake([]byte, 6),\n\t)\n\tcopy(rai.Payload[0:3], plmn)\n\tbinary.BigEndian.PutUint16(rai.Payload[3:5], lac)\n\trai.Payload[5] = rac\n\n\treturn rai\n}\n\n// RouteingAreaIdentity returns RouteingAreaIdentity value if type matches.\nfunc (i *IE) RouteingAreaIdentity() ([]byte, error) {\n\tif i.Type != RouteingAreaIdentity {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustRouteingAreaIdentity returns RouteingAreaIdentity in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRouteingAreaIdentity() []byte {\n\tv, _ := i.RouteingAreaIdentity()\n\treturn v\n}\n\n// MCC returns MCC value if type matches.\nfunc (i *IE) MCC() (string, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 2 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.SwappedBytesToStr(i.Payload[0:2], false), nil\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMCC returns MCC in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMCC() string {\n\tv, _ := i.MCC()\n\treturn v\n}\n\n// MNC returns MNC value if type matches.\nfunc (i *IE) MNC() (string, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 2 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.SwappedBytesToStr(i.Payload[1:2], true), nil\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMNC returns MNC in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMNC() string {\n\tv, _ := i.MNC()\n\treturn v\n}\n\n// LAC returns LAC value if type matches.\nfunc (i *IE) LAC() (uint16, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 5 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[3:5]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustLAC returns LAC in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustLAC() uint16 {\n\tv, _ := i.LAC()\n\treturn v\n}\n\n// RAC returns RAC value if type matches.\nfunc (i *IE) RAC() (uint8, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 6 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[5], nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustRAC returns RAC in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRAC() uint8 {\n\tv, _ := i.RAC()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/recovery.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewRecovery creates a new Recovery IE.\nfunc NewRecovery(recovery uint8) *IE {\n\treturn newUint8ValIE(Recovery, recovery)\n}\n\n// Recovery returns Recovery value if type matches.\nfunc (i *IE) Recovery() (uint8, error) {\n\tif i.Type != Recovery {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustRecovery returns Recovery in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRecovery() uint8 {\n\tv, _ := i.Recovery()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/reordering-required.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewReorderingRequired creates a new ReorderingRequired IE.\nfunc NewReorderingRequired(required bool) *IE {\n\tif required {\n\t\treturn New(ReorderingRequired, []byte{0xff})\n\t}\n\treturn New(ReorderingRequired, []byte{0xfe})\n}\n\n// ReorderingRequired returns ReorderingRequired value in bool if type matches.\nfunc (i *IE) ReorderingRequired() bool {\n\tif i.Type != ReorderingRequired {\n\t\treturn false\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn false\n\t}\n\n\treturn i.Payload[0]&0x01 == 1\n}\n"
  },
  {
    "path": "gtpv0/ie/selection-mode.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewSelectionMode creates a new SelectionMode IE.\n// Note that exactly one of the parameters should be set to true.\n// Otherwise, you'll get the unexpected result.\nfunc NewSelectionMode(mode uint8) *IE {\n\treturn newUint8ValIE(SelectionMode, mode)\n}\n\n// SelectionMode returns SelectionMode value if type matches.\nfunc (i *IE) SelectionMode() (uint8, error) {\n\tif i.Type != SelectionMode {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustSelectionMode returns SelectionMode in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustSelectionMode() uint8 {\n\tv, _ := i.SelectionMode()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/ie/tlli.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewTemporaryLogicalLinkIdentity creates a new TemporaryLogicalLinkIdentity IE.\nfunc NewTemporaryLogicalLinkIdentity(tlli uint32) *IE {\n\treturn newUint32ValIE(TemporaryLogicalLinkIdentity, tlli)\n}\n\n// TemporaryLogicalLinkIdentity returns TemporaryLogicalLinkIdentity value in uint32 if type matches.\nfunc (i *IE) TemporaryLogicalLinkIdentity() (uint32, error) {\n\tif i.Type != TemporaryLogicalLinkIdentity {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload), nil\n}\n\n// MustTemporaryLogicalLinkIdentity returns TemporaryLogicalLinkIdentity in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTemporaryLogicalLinkIdentity() uint32 {\n\tv, _ := i.TemporaryLogicalLinkIdentity()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv0/message/create-pdp-context-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// CreatePDPContextRequest is a CreatePDPContextRequest Header and its IEs above.\ntype CreatePDPContextRequest struct {\n\t*Header\n\tRAI                       *ie.IE\n\tQoSProfile                *ie.IE\n\tRecovery                  *ie.IE\n\tSelectionMode             *ie.IE\n\tFlowLabelDataI            *ie.IE\n\tFlowLabelSignalling       *ie.IE\n\tEndUserAddress            *ie.IE\n\tAPN                       *ie.IE\n\tPCO                       *ie.IE\n\tSGSNAddressForSignalling  *ie.IE\n\tSGSNAddressForUserTraffic *ie.IE\n\tMSISDN                    *ie.IE\n\tPrivateExtension          *ie.IE\n\tAdditionalIEs             []*ie.IE\n}\n\n// NewCreatePDPContextRequest creates a new CreatePDPContextRequest.\nfunc NewCreatePDPContextRequest(seq, label uint16, tid uint64, ies ...*ie.IE) *CreatePDPContextRequest {\n\tc := &CreatePDPContextRequest{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeCreatePDPContextRequest, seq, label, tid, nil,\n\t\t),\n\t}\n\n\t// Optional IEs and Private Extensions, or any arbitrary IE.\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tc.RAI = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.SelectionMode:\n\t\t\tc.SelectionMode = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tc.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tc.FlowLabelSignalling = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.AccessPointName:\n\t\t\tc.APN = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.SGSNAddressForSignalling == nil {\n\t\t\t\tc.SGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tc.SGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.MSISDN:\n\t\t\tc.MSISDN = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal returns the byte sequence generated from a CreatePDPContextRequest.\nfunc (c *CreatePDPContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (c *CreatePDPContextRequest) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.RAI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SelectionMode; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelDataI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MSISDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreatePDPContextRequest parses a given byte sequence as a CreatePDPContextRequest.\nfunc ParseCreatePDPContextRequest(b []byte) (*CreatePDPContextRequest, error) {\n\tc := &CreatePDPContextRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a CreatePDPContextRequest.\nfunc (c *CreatePDPContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tc.RAI = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.SelectionMode:\n\t\t\tc.SelectionMode = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tc.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tc.FlowLabelSignalling = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.AccessPointName:\n\t\t\tc.APN = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.SGSNAddressForSignalling == nil {\n\t\t\t\tc.SGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tc.SGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.MSISDN:\n\t\t\tc.MSISDN = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (c *CreatePDPContextRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.RAI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SelectionMode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MSISDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreatePDPContextRequest) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreatePDPContextRequest) MessageTypeName() string {\n\treturn \"Create PDP Context Request\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (c *CreatePDPContextRequest) TID() string {\n\treturn c.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/create-pdp-context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreatePDPContextRequest into bytes.\n//\n// Deprecated: use CreatePDPContextRequest.Marshal instead.\nfunc (c *CreatePDPContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"CreatePDPContextRequest.Serialize is deprecated. use CreatePDPContextRequest.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreatePDPContextRequest into bytes given as b.\n//\n// Deprecated: use CreatePDPContextRequest.MarshalTo instead.\nfunc (c *CreatePDPContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"CreatePDPContextRequest.SerializeTo is deprecated. use CreatePDPContextRequest.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreatePDPContextRequest decodes bytes as CreatePDPContextRequest.\n//\n// Deprecated: use ParseCreatePDPContextRequest instead.\nfunc DecodeCreatePDPContextRequest(b []byte) (*CreatePDPContextRequest, error) {\n\tlog.Println(\"DecodeCreatePDPContextRequest is deprecated. use ParseCreatePDPContextRequest instead\")\n\treturn ParseCreatePDPContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as CreatePDPContextRequest.\n//\n// Deprecated: use CreatePDPContextRequest.UnmarshalBinary instead.\nfunc (c *CreatePDPContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreatePDPContextRequest.DecodeFromBytes is deprecated. use CreatePDPContextRequest.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreatePDPContextRequest.\n//\n// Deprecated: use CreatePDPContextRequest.MarshalLen instead.\nfunc (c *CreatePDPContextRequest) Len() int {\n\tlog.Println(\"CreatePDPContextRequest.Len is deprecated. use CreatePDPContextRequest.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/create-pdp-context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestCreatePDPContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"mandatory-only\",\n\t\t\tStructured: message.NewCreatePDPContextRequest(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewQualityOfServiceProfile(1, 1, 1, 1, 1),\n\t\t\t\tie.NewSelectionMode(gtpv0.SelectionModeMSorNetworkProvidedAPNSubscribedVerified),\n\t\t\t\tie.NewFlowLabelDataI(11),\n\t\t\t\tie.NewFlowLabelSignalling(22),\n\t\t\t\tie.NewEndUserAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewAccessPointName(\"some.apn.example\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t\tie.NewGSNAddress(\"3.3.3.3\"),\n\t\t\t\tie.NewMSISDN(\"819012345678\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x10, 0x00, 0x41,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// QualityOfServiceProfile\n\t\t\t\t0x06, 0x09, 0x11, 0x01,\n\t\t\t\t// SelectionMode\n\t\t\t\t0x0f, 0xf0,\n\t\t\t\t// FlowLabelDataI\n\t\t\t\t0x10, 0x00, 0x0b,\n\t\t\t\t// FlowLabelSignalling\n\t\t\t\t0x11, 0x00, 0x16,\n\t\t\t\t// EndUserAddress\n\t\t\t\t0x80, 0x00, 0x06, 0xf1, 0x21, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// AccessPointName\n\t\t\t\t0x83, 0x00, 0x11, 0x04, 0x73, 0x6f, 0x6d, 0x65,\n\t\t\t\t0x03, 0x61, 0x70, 0x6e, 0x07, 0x65, 0x78, 0x61,\n\t\t\t\t0x6d, 0x70, 0x6c, 0x65,\n\t\t\t\t// SGSNAddressForSignalling\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// SGSNAddressForUserData\n\t\t\t\t0x85, 0x00, 0x04, 0x03, 0x03, 0x03, 0x03,\n\t\t\t\t// MSISDN\n\t\t\t\t0x86, 0x00, 0x07, 0x91, 0x18, 0x09, 0x21, 0x43,\n\t\t\t\t0x65, 0x87,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreatePDPContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/create-pdp-context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// CreatePDPContextResponse is a CreatePDPContextResponse Header and its IEs above.\ntype CreatePDPContextResponse struct {\n\t*Header\n\tCause                     *ie.IE\n\tQoSProfile                *ie.IE\n\tReorderingRequired        *ie.IE\n\tRecovery                  *ie.IE\n\tFlowLabelDataI            *ie.IE\n\tFlowLabelSignalling       *ie.IE\n\tChargingID                *ie.IE\n\tEndUserAddress            *ie.IE\n\tPCO                       *ie.IE\n\tGGSNAddressForSignalling  *ie.IE\n\tGGSNAddressForUserTraffic *ie.IE\n\tChargingGatewayAddress    *ie.IE\n\tPrivateExtension          *ie.IE\n\tAdditionalIEs             []*ie.IE\n}\n\n// NewCreatePDPContextResponse creates a new CreatePDPContextResponse.\nfunc NewCreatePDPContextResponse(seq, label uint16, tid uint64, ies ...*ie.IE) *CreatePDPContextResponse {\n\tc := &CreatePDPContextResponse{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeCreatePDPContextResponse, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.ReorderingRequired:\n\t\t\tc.ReorderingRequired = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tc.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tc.FlowLabelSignalling = i\n\t\tcase ie.ChargingID:\n\t\t\tc.ChargingID = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.GGSNAddressForSignalling == nil {\n\t\t\t\tc.GGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tc.GGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tc.ChargingGatewayAddress = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal returns the byte sequence generated from a CreatePDPContextResponse.\nfunc (c *CreatePDPContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (c *CreatePDPContextResponse) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ReorderingRequired; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelDataI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreatePDPContextResponse parses a given byte sequence as a CreatePDPContextResponse.\nfunc ParseCreatePDPContextResponse(b []byte) (*CreatePDPContextResponse, error) {\n\tc := &CreatePDPContextResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a CreatePDPContextResponse.\nfunc (c *CreatePDPContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.ReorderingRequired:\n\t\t\tc.ReorderingRequired = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tc.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tc.FlowLabelSignalling = i\n\t\tcase ie.ChargingID:\n\t\t\tc.ChargingID = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.GGSNAddressForSignalling == nil {\n\t\t\t\tc.GGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tc.GGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tc.ChargingGatewayAddress = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (c *CreatePDPContextResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ReorderingRequired; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.FlowLabelSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreatePDPContextResponse) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreatePDPContextResponse) MessageTypeName() string {\n\treturn \"Create PDP Context Response\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (c *CreatePDPContextResponse) TID() string {\n\treturn c.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/create-pdp-context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreatePDPContextResponse into bytes.\n//\n// Deprecated: use CreatePDPContextResponse.Marshal instead.\nfunc (c *CreatePDPContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"CreatePDPContextResponse.Serialize is deprecated. use CreatePDPContextResponse.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreatePDPContextResponse into bytes given as b.\n//\n// Deprecated: use CreatePDPContextResponse.MarshalTo instead.\nfunc (c *CreatePDPContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"CreatePDPContextResponse.SerializeTo is deprecated. use CreatePDPContextResponse.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreatePDPContextResponse decodes bytes as CreatePDPContextResponse.\n//\n// Deprecated: use ParseCreatePDPContextResponse instead.\nfunc DecodeCreatePDPContextResponse(b []byte) (*CreatePDPContextResponse, error) {\n\tlog.Println(\"DecodeCreatePDPContextResponse is deprecated. use ParseCreatePDPContextResponse instead\")\n\treturn ParseCreatePDPContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as CreatePDPContextResponse.\n//\n// Deprecated: use CreatePDPContextResponse.UnmarshalBinary instead.\nfunc (c *CreatePDPContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreatePDPContextResponse.DecodeFromBytes is deprecated. use CreatePDPContextResponse.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreatePDPContextResponse.\n//\n// Deprecated: use CreatePDPContextResponse.MarshalLen instead.\nfunc (c *CreatePDPContextResponse) Len() int {\n\tlog.Println(\"CreatePDPContextResponse.Len is deprecated. use CreatePDPContextResponse.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/create-pdp-context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestCreatePDPContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"request-accepted\",\n\t\t\tStructured: message.NewCreatePDPContextResponse(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewCause(gtpv0.CauseRequestAccepted),\n\t\t\t\tie.NewQualityOfServiceProfile(1, 1, 1, 1, 1),\n\t\t\t\tie.NewReorderingRequired(false),\n\t\t\t\tie.NewFlowLabelDataI(11),\n\t\t\t\tie.NewFlowLabelSignalling(22),\n\t\t\t\tie.NewChargingID(0xff),\n\t\t\t\tie.NewEndUserAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t\tie.NewGSNAddress(\"3.3.3.3\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x11, 0x00, 0x2a,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x80,\n\t\t\t\t// QualityOfServiceProfile\n\t\t\t\t0x06, 0x09, 0x11, 0x01,\n\t\t\t\t// ReorderingRequired\n\t\t\t\t0x08, 0xfe,\n\t\t\t\t// FlowLabelDataI\n\t\t\t\t0x10, 0x00, 0x0b,\n\t\t\t\t// FlowLabelSignalling\n\t\t\t\t0x11, 0x00, 0x16,\n\t\t\t\t// ChargingID\n\t\t\t\t0x7f, 0x00, 0x00, 0x00, 0xff,\n\t\t\t\t// EndUserAddress\n\t\t\t\t0x80, 0x00, 0x06, 0xf1, 0x21, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// SGSNAddressForSignalling\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// SGSNAddressForUserData\n\t\t\t\t0x85, 0x00, 0x04, 0x03, 0x03, 0x03, 0x03,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"no-resources\",\n\t\t\tStructured: message.NewCreatePDPContextResponse(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewCause(gtpv0.CauseNoResourcesAvailable),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x11, 0x00, 0x02,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0xc7,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreatePDPContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/delete-pdp-context-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE fild.\n\npackage message\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// DeletePDPContextRequest is a DeletePDPContextRequest Header and its AdditionalIEs abovd.\ntype DeletePDPContextRequest struct {\n\t*Header\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDeletePDPContextRequest creates a new DeletePDPContextRequest.\nfunc NewDeletePDPContextRequest(seq, label uint16, tid uint64, ies ...*ie.IE) *DeletePDPContextRequest {\n\td := &DeletePDPContextRequest{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeDeletePDPContextRequest, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal returns the byte sequence generated from a DeletePDPContextRequest.\nfunc (d *DeletePDPContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (d *DeletePDPContextRequest) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeletePDPContextRequest parses a given byte sequence as a DeletePDPContextRequest.\nfunc ParseDeletePDPContextRequest(b []byte) (*DeletePDPContextRequest, error) {\n\td := &DeletePDPContextRequest{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a DeletePDPContextRequest.\nfunc (d *DeletePDPContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to Parse Header: %w\", err)\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (d *DeletePDPContextRequest) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeletePDPContextRequest) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeletePDPContextRequest) MessageTypeName() string {\n\treturn \"Delete PDP Context Request\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (d *DeletePDPContextRequest) TID() string {\n\treturn d.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/delete-pdp-context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeletePDPContextRequest into bytes.\n//\n// Deprecated: use DeletePDPContextRequest.Marshal instead.\nfunc (d *DeletePDPContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"DeletePDPContextRequest.Serialize is deprecated. use DeletePDPContextRequest.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeletePDPContextRequest into bytes given as b.\n//\n// Deprecated: use DeletePDPContextRequest.MarshalTo instead.\nfunc (d *DeletePDPContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"DeletePDPContextRequest.SerializeTo is deprecated. use DeletePDPContextRequest.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeletePDPContextRequest decodes bytes as DeletePDPContextRequest.\n//\n// Deprecated: use ParseDeletePDPContextRequest instead.\nfunc DecodeDeletePDPContextRequest(b []byte) (*DeletePDPContextRequest, error) {\n\tlog.Println(\"DecodeDeletePDPContextRequest is deprecated. use ParseDeletePDPContextRequest instead\")\n\treturn ParseDeletePDPContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as DeletePDPContextRequest.\n//\n// Deprecated: use DeletePDPContextRequest.UnmarshalBinary instead.\nfunc (d *DeletePDPContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeletePDPContextRequest.DecodeFromBytes is deprecated. use DeletePDPContextRequest.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeletePDPContextRequest.\n//\n// Deprecated: use DeletePDPContextRequest.MarshalLen instead.\nfunc (d *DeletePDPContextRequest) Len() int {\n\tlog.Println(\"DeletePDPContextRequest.Len is deprecated. use DeletePDPContextRequest.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/delete-pdp-context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestDeletePDPContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"normal\",\n\t\t\tStructured: message.NewDeletePDPContextRequest(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x14, 0x00, 0x00,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeletePDPContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/delete-pdp-context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE fild.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// DeletePDPContextResponse is a DeletePDPContextResponse Header and its AdditionalIEs abovd.\ntype DeletePDPContextResponse struct {\n\t*Header\n\tCause            *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDeletePDPContextResponse creates a new DeletePDPContextResponse.\nfunc NewDeletePDPContextResponse(seq, label uint16, tid uint64, ies ...*ie.IE) *DeletePDPContextResponse {\n\td := &DeletePDPContextResponse{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeDeletePDPContextResponse, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal returns the byte sequence generated from a DeletePDPContextResponsd.\nfunc (d *DeletePDPContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (d *DeletePDPContextResponse) MarshalTo(b []byte) error {\n\t// XXX - add validation!\n\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeletePDPContextResponse parses a given byte sequence as a DeletePDPContextResponsd.\nfunc ParseDeletePDPContextResponse(b []byte) (*DeletePDPContextResponse, error) {\n\td := &DeletePDPContextResponse{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a DeletePDPContextResponsd.\nfunc (d *DeletePDPContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (d *DeletePDPContextResponse) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeletePDPContextResponse) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeletePDPContextResponse) MessageTypeName() string {\n\treturn \"Delete PDP Context Response\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (d *DeletePDPContextResponse) TID() string {\n\treturn d.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/delete-pdp-context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeletePDPContextResponse into bytes.\n//\n// Deprecated: use DeletePDPContextResponse.Marshal instead.\nfunc (d *DeletePDPContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"DeletePDPContextResponse.Serialize is deprecated. use DeletePDPContextResponse.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeletePDPContextResponse into bytes given as b.\n//\n// Deprecated: use DeletePDPContextResponse.MarshalTo instead.\nfunc (d *DeletePDPContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"DeletePDPContextResponse.SerializeTo is deprecated. use DeletePDPContextResponse.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeletePDPContextResponse decodes bytes as DeletePDPContextResponse.\n//\n// Deprecated: use ParseDeletePDPContextResponse instead.\nfunc DecodeDeletePDPContextResponse(b []byte) (*DeletePDPContextResponse, error) {\n\tlog.Println(\"DecodeDeletePDPContextResponse is deprecated. use ParseDeletePDPContextResponse instead\")\n\treturn ParseDeletePDPContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as DeletePDPContextResponse.\n//\n// Deprecated: use DeletePDPContextResponse.UnmarshalBinary instead.\nfunc (d *DeletePDPContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeletePDPContextResponse.DecodeFromBytes is deprecated. use DeletePDPContextResponse.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeletePDPContextResponse.\n//\n// Deprecated: use DeletePDPContextResponse.MarshalLen instead.\nfunc (d *DeletePDPContextResponse) Len() int {\n\tlog.Println(\"DeletePDPContextResponse.Len is deprecated. use DeletePDPContextResponse.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/delete-pdp-context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestDeletePDPContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"request-accepted\",\n\t\t\tStructured: message.NewDeletePDPContextResponse(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewCause(gtpv0.CauseRequestAccepted),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Hewader\n\t\t\t\t0x1e, 0x15, 0x00, 0x02,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeletePDPContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/echo-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// EchoRequest is a EchoRequest Header and its AdditionalIEs above.\ntype EchoRequest struct {\n\t*Header\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewEchoRequest creates a new EchoRequest.\nfunc NewEchoRequest(seq, label uint16, tid uint64, ies ...*ie.IE) *EchoRequest {\n\te := &EchoRequest{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeEchoRequest, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EchoRequest.\nfunc (e *EchoRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EchoRequest) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEchoRequest parses a given byte sequence as a EchoRequest.\nfunc ParseEchoRequest(b []byte) (*EchoRequest, error) {\n\te := &EchoRequest{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a EchoRequest.\nfunc (e *EchoRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to Parse Header: %w\", err)\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EchoRequest) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EchoRequest) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EchoRequest) MessageTypeName() string {\n\treturn \"Echo Request\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (e *EchoRequest) TID() string {\n\treturn e.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/echo-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes EchoRequest into bytes.\n//\n// Deprecated: use EchoRequest.Marshal instead.\nfunc (e *EchoRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"EchoRequest.Serialize is deprecated. use EchoRequest.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes EchoRequest into bytes given as b.\n//\n// Deprecated: use EchoRequest.MarshalTo instead.\nfunc (e *EchoRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"EchoRequest.SerializeTo is deprecated. use EchoRequest.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeEchoRequest decodes bytes as EchoRequest.\n//\n// Deprecated: use ParseEchoRequest instead.\nfunc DecodeEchoRequest(b []byte) (*EchoRequest, error) {\n\tlog.Println(\"DecodeEchoRequest is deprecated. use ParseEchoRequest instead\")\n\treturn ParseEchoRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as EchoRequest.\n//\n// Deprecated: use EchoRequest.UnmarshalBinary instead.\nfunc (e *EchoRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"EchoRequest.DecodeFromBytes is deprecated. use EchoRequest.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of EchoRequest.\n//\n// Deprecated: use EchoRequest.MarshalLen instead.\nfunc (e *EchoRequest) Len() int {\n\tlog.Println(\"EchoRequest.Len is deprecated. use EchoRequest.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/echo-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestEchoRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"normal\",\n\t\t\tStructured: message.NewEchoRequest(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x01, 0x00, 0x00,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEchoRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/echo-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// EchoResponse is a EchoResponse Header and its AdditionalIEs above.\ntype EchoResponse struct {\n\t*Header\n\tRecovery         *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewEchoResponse creates a new GTP.\nfunc NewEchoResponse(seq, label uint16, tid uint64, ies ...*ie.IE) *EchoResponse {\n\te := &EchoResponse{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeEchoResponse, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EchoResponse.\nfunc (e *EchoResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EchoResponse) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEchoResponse parses a given byte sequence as a EchoResponse.\nfunc ParseEchoResponse(b []byte) (*EchoResponse, error) {\n\te := &EchoResponse{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a EchoResponse.\nfunc (e *EchoResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EchoResponse) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EchoResponse) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EchoResponse) MessageTypeName() string {\n\treturn \"Echo Response\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (e *EchoResponse) TID() string {\n\treturn e.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/echo-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes EchoResponse into bytes.\n//\n// Deprecated: use EchoResponse.Marshal instead.\nfunc (e *EchoResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"EchoResponse.Serialize is deprecated. use EchoResponse.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes EchoResponse into bytes given as b.\n//\n// Deprecated: use EchoResponse.MarshalTo instead.\nfunc (e *EchoResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"EchoResponse.SerializeTo is deprecated. use EchoResponse.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeEchoResponse decodes bytes as EchoResponse.\n//\n// Deprecated: use ParseEchoResponse instead.\nfunc DecodeEchoResponse(b []byte) (*EchoResponse, error) {\n\tlog.Println(\"DecodeEchoResponse is deprecated. use ParseEchoResponse instead\")\n\treturn ParseEchoResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as EchoResponse.\n//\n// Deprecated: use EchoResponse.UnmarshalBinary instead.\nfunc (e *EchoResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"EchoResponse.DecodeFromBytes is deprecated. use EchoResponse.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of EchoResponse.\n//\n// Deprecated: use EchoResponse.MarshalLen instead.\nfunc (e *EchoResponse) Len() int {\n\tlog.Println(\"EchoResponse.Len is deprecated. use EchoResponse.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/echo-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestEchoResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"with-recovery\",\n\t\t\tStructured: message.NewEchoResponse(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewRecovery(0x80),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Hewader\n\t\t\t\t0x1e, 0x02, 0x00, 0x02,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Recovery\n\t\t\t\t0x0e, 0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEchoResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"errors\"\n\n// Error definitions.\nvar (\n\tErrInvalidLength     = errors.New(\"got invalid length\")\n\tErrTooShortToMarshal = errors.New(\"too short to Marshal\")\n\tErrTooShortToParse   = errors.New(\"too short to Parse as GTPv0\")\n)\n"
  },
  {
    "path": "gtpv0/message/generic.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// Generic is a Generic Header and its IEs above.\ntype Generic struct {\n\t*Header\n\tIEs []*ie.IE\n}\n\n// NewGeneric creates a new GTPv0 Generic.\nfunc NewGeneric(msgType uint8, seq, label uint16, tid uint64, ie ...*ie.IE) *Generic {\n\tg := &Generic{\n\t\tHeader: NewHeader(0x1e, msgType, seq, label, tid, nil),\n\t}\n\n\tfor _, i := range ie {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tg.IEs = append(g.IEs, i)\n\t}\n\n\tg.SetLength()\n\treturn g\n}\n\n// Marshal returns the byte sequence generated from a Generic.\nfunc (g *Generic) Marshal() ([]byte, error) {\n\tb := make([]byte, g.MarshalLen())\n\tif err := g.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (g *Generic) MarshalTo(b []byte) error {\n\tif g.Header.Payload != nil {\n\t\tg.Header.Payload = nil\n\t}\n\tg.Header.Payload = make([]byte, g.MarshalLen()-g.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range g.IEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(g.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tg.Header.SetLength()\n\treturn g.Header.MarshalTo(b)\n}\n\n// ParseGeneric parses a given byte sequence as a Generic.\nfunc ParseGeneric(b []byte) (*Generic, error) {\n\tg := &Generic{}\n\tif err := g.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn g, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a Generic.\nfunc (g *Generic) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tg.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(g.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tg.IEs, err = ie.ParseMultiIEs(g.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (g *Generic) MarshalLen() int {\n\tl := g.Header.MarshalLen() - len(g.Header.Payload)\n\tfor _, ie := range g.IEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (g *Generic) SetLength() {\n\tg.Header.Length = uint16(g.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (g *Generic) MessageTypeName() string {\n\treturn fmt.Sprintf(\"Unknown (%d)\", g.Type)\n}\n\n// TID returns the TID in human-readable string.\nfunc (g *Generic) TID() string {\n\treturn g.tid()\n}\n\n// AddIE add IEs to Generic type of GTPv2 message and update Length field.\nfunc (g *Generic) AddIE(ie ...*ie.IE) {\n\tg.IEs = append(g.IEs, ie...)\n\tg.SetLength()\n}\n"
  },
  {
    "path": "gtpv0/message/generic_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Generic into bytes.\n//\n// Deprecated: use Generic.Marshal instead.\nfunc (g *Generic) Serialize() ([]byte, error) {\n\tlog.Println(\"Generic.Serialize is deprecated. use Generic.Marshal instead\")\n\treturn g.Marshal()\n}\n\n// SerializeTo serializes Generic into bytes given as b.\n//\n// Deprecated: use Generic.MarshalTo instead.\nfunc (g *Generic) SerializeTo(b []byte) error {\n\tlog.Println(\"Generic.SerializeTo is deprecated. use Generic.MarshalTo instead\")\n\treturn g.MarshalTo(b)\n}\n\n// DecodeGeneric decodes bytes as Generic.\n//\n// Deprecated: use ParseGeneric instead.\nfunc DecodeGeneric(b []byte) (*Generic, error) {\n\tlog.Println(\"DecodeGeneric is deprecated. use ParseGeneric instead\")\n\treturn ParseGeneric(b)\n}\n\n// DecodeFromBytes decodes bytes as Generic.\n//\n// Deprecated: use Generic.UnmarshalBinary instead.\nfunc (g *Generic) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"Generic.DecodeFromBytes is deprecated. use Generic.UnmarshalBinary instead\")\n\treturn g.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of Generic.\n//\n// Deprecated: use Generic.MarshalLen instead.\nfunc (g *Generic) Len() int {\n\tlog.Println(\"Generic.Len is deprecated. use Generic.MarshalLen instead\")\n\treturn g.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/generic_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestGeneric(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"echo-req\",\n\t\t\tStructured: message.NewGeneric(\n\t\t\t\tmessage.MsgTypeEchoRequest, testutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,\n\t\t\t\t0xff, 0xff, 0xff, 0xff, 0x21, 0x43, 0x65, 0x87,\n\t\t\t\t0x09, 0x21, 0x43, 0x55,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"echo-res\",\n\t\t\tStructured: message.NewGeneric(\n\t\t\t\tmessage.MsgTypeEchoResponse, testutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewRecovery(0x80),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Hewader\n\t\t\t\t0x1e, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,\n\t\t\t\t0xff, 0xff, 0xff, 0xff, 0x21, 0x43, 0x65, 0x87,\n\t\t\t\t0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Recovery\n\t\t\t\t0x0e, 0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseGeneric(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/header.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// Header is a GTPv1 common header.\ntype Header struct {\n\tFlags          uint8\n\tType           uint8\n\tLength         uint16\n\tSequenceNumber uint16\n\tSndcpNumber    uint8\n\tFlowLabel      uint16\n\tTID            uint64\n\tPayload        []byte\n}\n\n// NewHeader creates a new Header.\nfunc NewHeader(flags, mtype uint8, seq, label uint16, tid uint64, payload []byte) *Header {\n\th := &Header{\n\t\tFlags:          flags,\n\t\tType:           mtype,\n\t\tSequenceNumber: seq,\n\t\tFlowLabel:      label,\n\t\tSndcpNumber:    0xff,\n\t\tTID:            tid,\n\t\tPayload:        payload,\n\t}\n\th.SetLength()\n\n\treturn h\n}\n\n// HeaderFlags returns a Header Flag built by its components given as arguments.\nfunc HeaderFlags(v, p, s int) uint8 {\n\treturn uint8(\n\t\t((v & 0x7) << 5) | ((p & 0x1) << 4) | (s & 0x1) | 0x0e,\n\t)\n}\n\n// Marshal returns the byte sequence generated from an IE instance.\nfunc (h *Header) Marshal() ([]byte, error) {\n\tb := make([]byte, h.MarshalLen())\n\tif err := h.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (h *Header) MarshalTo(b []byte) error {\n\tif len(b) < h.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tb[0] = h.Flags\n\tb[1] = h.Type\n\tbinary.BigEndian.PutUint16(b[2:4], h.Length)\n\tbinary.BigEndian.PutUint16(b[4:6], h.SequenceNumber)\n\tbinary.BigEndian.PutUint16(b[6:8], h.FlowLabel)\n\tbinary.BigEndian.PutUint32(b[8:12], uint32(int(h.SndcpNumber)<<24|0xffffff))\n\tbinary.BigEndian.PutUint64(b[12:20], h.TID)\n\t// two bytes of padding before payload.\n\tcopy(b[20:h.MarshalLen()], h.Payload)\n\treturn nil\n}\n\n// ParseHeader Parses given byte sequence as a GTPv1 header.\nfunc ParseHeader(b []byte) (*Header, error) {\n\th := &Header{}\n\tif err := h.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn h, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in GTPv1 header.\nfunc (h *Header) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 20 {\n\t\treturn ErrTooShortToParse\n\t}\n\th.Flags = b[0]\n\th.Type = b[1]\n\th.Length = binary.BigEndian.Uint16(b[2:4])\n\th.SequenceNumber = binary.BigEndian.Uint16(b[4:6])\n\th.FlowLabel = binary.BigEndian.Uint16(b[6:8])\n\th.SndcpNumber = b[9]\n\th.TID = binary.BigEndian.Uint64(b[12:20])\n\n\tif int(h.Length)+20 != l {\n\t\th.Payload = b[20:]\n\t\treturn nil\n\t}\n\th.Payload = b[20 : 20+h.Length]\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Header.\nfunc (h *Header) MarshalLen() int {\n\treturn 20 + len(h.Payload)\n}\n\n// SetLength sets the length in Length field.\nfunc (h *Header) SetLength() {\n\th.Length = uint16(len(h.Payload))\n}\n\n// String returns the GTPv1 header values in human readable format.\nfunc (h *Header) String() string {\n\treturn fmt.Sprintf(\"{Flags: %#x, Type: %#x, Length: %d, SequenceNumber: %#04x, FlowLabel: %#04x, SndcpNumber: %#02x, TID: %#016x, Payload: %#v}\",\n\t\th.Flags,\n\t\th.Type,\n\t\th.Length,\n\t\th.SequenceNumber,\n\t\th.FlowLabel,\n\t\th.SndcpNumber,\n\t\th.TID,\n\t\th.Payload,\n\t)\n}\n\n// tid returns the tid in human-readable string.\nfunc (h *Header) tid() string {\n\tb := make([]byte, 8)\n\tbinary.BigEndian.PutUint64(b, h.TID)\n\n\treturn utils.SwappedBytesToStr(b, false)\n}\n\n// Version returns the GTP version.\nfunc (h *Header) Version() int {\n\treturn 0\n}\n\n// MessageType returns the type of message.\nfunc (h *Header) MessageType() uint8 {\n\treturn h.Type\n}\n"
  },
  {
    "path": "gtpv0/message/header_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Header into bytes.\n//\n// Deprecated: use Header.Marshal instead.\nfunc (h *Header) Serialize() ([]byte, error) {\n\tlog.Println(\"Header.Serialize is deprecated. use Header.Marshal instead\")\n\treturn h.Marshal()\n}\n\n// SerializeTo serializes Header into bytes given as b.\n//\n// Deprecated: use Header.MarshalTo instead.\nfunc (h *Header) SerializeTo(b []byte) error {\n\tlog.Println(\"Header.SerializeTo is deprecated. use Header.MarshalTo instead\")\n\treturn h.MarshalTo(b)\n}\n\n// DecodeHeader decodes bytes as Header.\n//\n// Deprecated: use ParseHeader instead.\nfunc DecodeHeader(b []byte) (*Header, error) {\n\tlog.Println(\"DecodeHeader is deprecated. use ParseHeader instead\")\n\treturn ParseHeader(b)\n}\n\n// DecodeFromBytes decodes bytes as Header.\n//\n// Deprecated: use Header.UnmarshalBinary instead.\nfunc (h *Header) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"Header.DecodeFromBytes is deprecated. use Header.UnmarshalBinary instead\")\n\treturn h.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of Header.\n//\n// Deprecated: use Header.MarshalLen instead.\nfunc (h *Header) Len() int {\n\tlog.Println(\"Header.Len is deprecated. use Header.MarshalLen instead\")\n\treturn h.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/header_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestHeader(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"normal\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.HeaderFlags(\n\t\t\t\t\t0, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // N-PDU?\n\t\t\t\t), //Flags\n\t\t\t\t0x10, // Message type\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Flags\n\t\t\t\t0x1e,\n\t\t\t\t// MessageType\n\t\t\t\t0x10,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x04, 0x00, 0x01,\n\t\t\t\t// FlowLabel\n\t\t\t\t0x00, 0x00,\n\t\t\t\t// SndcpNumber\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// dummy Payload\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseHeader(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/message.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n/*\nPackage message provides encoding/decoding feature of GTPv0 protocol.\n*/\npackage message\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// MessageType definitions.\nconst (\n\t_ uint8 = iota\n\tMsgTypeEchoRequest\n\tMsgTypeEchoResponse\n\tMsgTypeVersionNotSupported\n\tMsgTypeNodeAliveRequest\n\tMsgTypeNodeAliveResponse\n\tMsgTypeRedirectionRequest\n\tMsgTypeRedirectionResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tMsgTypeCreatePDPContextRequest // 16\n\tMsgTypeCreatePDPContextResponse\n\tMsgTypeUpdatePDPContextRequest\n\tMsgTypeUpdatePDPContextResponse\n\tMsgTypeDeletePDPContextRequest\n\tMsgTypeDeletePDPContextResponse\n\tMsgTypeCreateAAPDPContextRequest\n\tMsgTypeCreateAAPDPContextResponse\n\tMsgTypeDeleteAAPDPContextRequest\n\tMsgTypeDeleteAAPDPContextResponse\n\tMsgTypeErrorIndication\n\tMsgTypePDUNotificationRequest\n\tMsgTypePDUNotificationResponse\n\tMsgTypePDUNotificationRejectRequest\n\tMsgTypePDUNotificationRejectResponse\n\t_\n\tMsgTypeSendRouteingInformationforGPRSRequest // 32\n\tMsgTypeSendRouteingInformationforGPRSResponse\n\tMsgTypeFailureReportRequest\n\tMsgTypeFailureReportResponse\n\tMsgTypeNoteMSGPRSPresentRequest\n\tMsgTypeNoteMSGPRSPresentResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tMsgTypeIdentificationRequest // 48\n\tMsgTypeIdentificationResponse\n\tMsgTypeSGSNContextRequest\n\tMsgTypeSGSNContextResponse\n\tMsgTypeSGSNContextAcknowledge\n\tMsgTypeDataRecordTransferRequest  = 240\n\tMsgTypeDataRecordTransferResponse = 241\n\tMsgTypeTPDU                       = 255\n)\n\n// Message is an interface that defines Message message.\ntype Message interface {\n\tMarshalTo([]byte) error\n\tUnmarshalBinary(b []byte) error\n\tMarshalLen() int\n\tString() string\n\tVersion() int\n\tMessageType() uint8\n\tMessageTypeName() string\n\tTID() string\n\n\t// deprecated\n\tSerializeTo([]byte) error\n\tDecodeFromBytes(b []byte) error\n}\n\n// Marshal returns the byte sequence generated from a Message instance.\n// Better to use MarshalXxx instead if you know the name of message to be Serialized.\nfunc Marshal(g Message) ([]byte, error) {\n\tb := make([]byte, g.MarshalLen())\n\tif err := g.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// Parse parses the given bytes as a Message.\nfunc Parse(b []byte) (Message, error) {\n\tif len(b) < 2 {\n\t\treturn nil, ErrTooShortToParse\n\t}\n\n\tvar g Message\n\n\tswitch b[1] {\n\tcase MsgTypeEchoRequest:\n\t\tg = &EchoRequest{}\n\tcase MsgTypeEchoResponse:\n\t\tg = &EchoResponse{}\n\t/* XXX - Implement!\n\tcase MsgTypeVersionNotSupported:\n\t\tg = &VerNotSupported{}\n\tcase MsgTypeNodeAliveRequest:\n\t\tg = &NodeAliveReq{}\n\tcase MsgTypeNodeAliveResponse:\n\t\tg = &NodeAliveRes{}\n\tcase MsgTypeRedirectionRequest:\n\t\tg = &RedirectionReq{}\n\tcase MsgTypeRedirectionResponse:\n\t\tg = &RedirectionRes{}\n\t*/\n\tcase MsgTypeCreatePDPContextRequest:\n\t\tg = &CreatePDPContextRequest{}\n\tcase MsgTypeCreatePDPContextResponse:\n\t\tg = &CreatePDPContextResponse{}\n\tcase MsgTypeUpdatePDPContextRequest:\n\t\tg = &UpdatePDPContextRequest{}\n\tcase MsgTypeUpdatePDPContextResponse:\n\t\tg = &UpdatePDPContextResponse{}\n\tcase MsgTypeDeletePDPContextRequest:\n\t\tg = &DeletePDPContextRequest{}\n\tcase MsgTypeDeletePDPContextResponse:\n\t\tg = &DeletePDPContextResponse{}\n\t/* XXX - Implement!\n\tcase MsgTypeCreateAAPDPContextRequest:\n\t\tg = &CreateAAPDPContextReq{}\n\tcase MsgTypeCreateAAPDPContextResponse:\n\t\tg = &CreateAAPDPContextRes{}\n\tcase MsgTypeDeleteAAPDPContextRequest:\n\t\tg = &DeleteAAPDPContextReq{}\n\tcase MsgTypeDeleteAAPDPContextResponse:\n\t\tg = &DeleteAAPDPContextRes{}\n\tcase MsgTypeErrorIndication:\n\t\tg = &ErrorInd{}\n\tcase MsgTypePDUNotificationRequest:\n\t\tg = &PDUNotificationReq{}\n\tcase MsgTypePDUNotificationResponse:\n\t\tg = &PDUNotificationRes{}\n\tcase MsgTypePDUNotificationRejectRequest:\n\t\tg = &PDUNotificationRejectReq{}\n\tcase MsgTypePDUNotificationRejectResponse:\n\t\tg = &PDUNotificationRejectRes{}\n\tcase MsgTypeSendRouteingInformationforGPRSRequest:\n\t\tg = &SendRouteingInformationforGPRSReq{}\n\tcase MsgTypeSendRouteingInformationforGPRSResponse:\n\t\tg = &SendRouteingInformationforGPRSRes{}\n\tcase MsgTypeFailureReportRequest:\n\t\tg = &FailureReportReq{}\n\tcase MsgTypeFailureReportResponse:\n\t\tg = &FailureReportRes{}\n\tcase MsgTypeNoteMSGPRSPresentRequest:\n\t\tg = &NoteMSGPRSPresentReq{}\n\tcase MsgTypeNoteMSGPRSPresentResponse:\n\t\tg = &NoteMSGPRSPresentRes{}\n\tcase MsgTypeIdentificationRequest:\n\t\tg = &IdentificationReq{}\n\tcase MsgTypeIdentificationResponse:\n\t\tg = &IdentificationRes{}\n\tcase MsgTypeSGSNContextRequest:\n\t\tg = &SGSNContextReq{}\n\tcase MsgTypeSGSNContextResponse:\n\t\tg = &SGSNContextRes{}\n\tcase MsgTypeSGSNContextAcknowledge:\n\t\tg = &SGSNContextAck{}\n\tcase MsgTypeDataRecordTransferRequest:\n\t\tg = &DataRecordTransferReq{}\n\tcase MsgTypeDataRecordTransferResponse:\n\t\tg = &DataRecordTransferRes{}\n\t*/\n\tcase MsgTypeTPDU:\n\t\tg = &TPDU{}\n\tdefault:\n\t\tg = &Generic{}\n\t}\n\n\tif err := g.UnmarshalBinary(b); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to Parse Message: %w\", err)\n\t}\n\treturn g, nil\n}\n\n// Decapsulate decapsulates given bytes and returns Payload in []byte.\nfunc Decapsulate(b []byte) ([]byte, error) {\n\theader, err := ParseHeader(b)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif header.Type != MsgTypeTPDU {\n\t\treturn nil, nil\n\t}\n\treturn header.Payload, nil\n}\n\n// Prettify returns a Message in prettified representation in string.\n//\n// Note that this relies much on reflect package, and thus the frequent use of\n// this function may have a serious impact on the performance of your software.\nfunc Prettify(m Message) string {\n\tname := m.MessageTypeName()\n\theader := strings.TrimSuffix(fmt.Sprint(m), \"}\")\n\n\tv := reflect.Indirect(reflect.ValueOf(m))\n\tn := v.NumField() - 1\n\tfields := make([]*field, n)\n\tfor i := 1; i < n+1; i++ { // Skip *Header\n\t\tfields[i-1] = &field{name: v.Type().Field(i).Name, maybeIE: v.Field(i).Interface()}\n\t}\n\n\treturn fmt.Sprintf(\"{%s: %s, IEs: [%v]}\", name, header, strings.Join(prettifyFields(fields), \", \"))\n}\n\ntype field struct {\n\tname    string\n\tmaybeIE interface{}\n}\n\nfunc prettifyFields(fields []*field) []string {\n\tret := []string{}\n\tfor _, field := range fields {\n\t\tif field.maybeIE == nil {\n\t\t\tret = append(ret, prettifyIE(field.name, nil))\n\t\t\tcontinue\n\t\t}\n\n\t\t// TODO: do this recursively?\n\t\tv, ok := field.maybeIE.(*ie.IE)\n\t\tif !ok {\n\t\t\t// only for AdditionalIEs field\n\t\t\tif ies, ok := field.maybeIE.([]*ie.IE); ok {\n\t\t\t\tvals := make([]string, len(ies))\n\t\t\t\tfor i, val := range ies {\n\t\t\t\t\tvals[i] = fmt.Sprint(val)\n\t\t\t\t}\n\t\t\t\tret = append(ret, fmt.Sprintf(\"{%s: [%v]}\", field.name, strings.Join(vals, \", \")))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tret = append(ret, prettifyIE(field.name, v))\n\t}\n\n\treturn ret\n}\n\nfunc prettifyIE(name string, i *ie.IE) string {\n\treturn fmt.Sprintf(\"{%s: %v}\", name, i)\n}\n"
  },
  {
    "path": "gtpv0/message/message_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Message into bytes.\n//\n// Deprecated: use Marshal instead.\nfunc Serialize(m Message) ([]byte, error) {\n\tlog.Println(\"Serialize is deprecated. use Marshal instead\")\n\treturn Marshal(m)\n}\n\n// Decode decodes bytes as Message.\n//\n// Deprecated: use Parse instead.\nfunc Decode(b []byte) (Message, error) {\n\tlog.Println(\"Decode is deprecated. use Parse instead\")\n\treturn Parse(b)\n}\n"
  },
  {
    "path": "gtpv0/message/message_fuzz_test.go",
    "content": "package message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := message.Parse(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n\nfunc FuzzHeaderParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := message.ParseHeader(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/t-pdu.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\n// TPDU represents a T-PDU type of GTPv0 message.\ntype TPDU struct {\n\t*Header\n}\n\n// NewTPDU creates a new TPDU.\nfunc NewTPDU(seq, label uint16, tid uint64, payload []byte) *TPDU {\n\tt := &TPDU{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeTPDU, seq, label, tid, payload,\n\t\t),\n\t}\n\tt.SetLength()\n\treturn t\n}\n\n// Marshal returns the byte sequence generated from a TPDU.\nfunc (t *TPDU) Marshal() ([]byte, error) {\n\tb := make([]byte, t.MarshalLen())\n\tif err := t.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (t *TPDU) MarshalTo(b []byte) error {\n\tif len(b) < t.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tt.Header.Payload = t.Payload\n\tt.Header.SetLength()\n\treturn t.Header.MarshalTo(b)\n}\n\n// ParseTPDU parses a given byte sequence as a TPDU.\nfunc ParseTPDU(b []byte) (*TPDU, error) {\n\tt := &TPDU{}\n\tif err := t.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn t, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a TPDU.\nfunc (t *TPDU) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tt.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.Payload = t.Header.Payload\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (t *TPDU) MarshalLen() int {\n\treturn t.Header.MarshalLen() - len(t.Header.Payload) + len(t.Payload)\n}\n\n// SetLength sets the length in Length field.\nfunc (t *TPDU) SetLength() {\n\tt.Header.Length = uint16(len(t.Payload))\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (t *TPDU) MessageTypeName() string {\n\treturn \"T-PDU\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (t *TPDU) TID() string {\n\treturn t.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/t-pdu_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes TPDU into bytes.\n//\n// Deprecated: use TPDU.Marshal instead.\nfunc (t *TPDU) Serialize() ([]byte, error) {\n\tlog.Println(\"TPDU.Serialize is deprecated. use TPDU.Marshal instead\")\n\treturn t.Marshal()\n}\n\n// SerializeTo serializes TPDU into bytes given as b.\n//\n// Deprecated: use TPDU.MarshalTo instead.\nfunc (t *TPDU) SerializeTo(b []byte) error {\n\tlog.Println(\"TPDU.SerializeTo is deprecated. use TPDU.MarshalTo instead\")\n\treturn t.MarshalTo(b)\n}\n\n// DecodeTPDU decodes bytes as TPDU.\n//\n// Deprecated: use ParseTPDU instead.\nfunc DecodeTPDU(b []byte) (*TPDU, error) {\n\tlog.Println(\"DecodeTPDU is deprecated. use ParseTPDU instead\")\n\treturn ParseTPDU(b)\n}\n\n// DecodeFromBytes decodes bytes as TPDU.\n//\n// Deprecated: use TPDU.UnmarshalBinary instead.\nfunc (t *TPDU) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"TPDU.DecodeFromBytes is deprecated. use TPDU.UnmarshalBinary instead\")\n\treturn t.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of TPDU.\n//\n// Deprecated: use TPDU.MarshalLen instead.\nfunc (t *TPDU) Len() int {\n\tlog.Println(\"TPDU.Len is deprecated. use TPDU.MarshalLen instead\")\n\treturn t.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/t-pdu_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestTPDU(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"normal\",\n\t\t\tStructured: message.NewTPDU(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\t[]byte{0xde, 0xad, 0xbe, 0xef},\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0xff, 0x00, 0x04,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// SNDPD\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Payload\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseTPDU(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/update-pdp-context-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// UpdatePDPContextRequest is a UpdatePDPContextRequest Header and its IEs above.\ntype UpdatePDPContextRequest struct {\n\t*Header\n\tRAI                       *ie.IE\n\tQoSProfile                *ie.IE\n\tRecovery                  *ie.IE\n\tFlowLabelDataI            *ie.IE\n\tFlowLabelSignalling       *ie.IE\n\tEndUserAddress            *ie.IE\n\tSGSNAddressForSignalling  *ie.IE\n\tSGSNAddressForUserTraffic *ie.IE\n\tPrivateExtension          *ie.IE\n\tAdditionalIEs             []*ie.IE\n}\n\n// NewUpdatePDPContextRequest creates a new UpdatePDPContextRequest.\nfunc NewUpdatePDPContextRequest(seq, label uint16, tid uint64, ies ...*ie.IE) *UpdatePDPContextRequest {\n\tu := &UpdatePDPContextRequest{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeUpdatePDPContextRequest, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tu.RAI = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tu.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tu.FlowLabelSignalling = i\n\t\tcase ie.EndUserAddress:\n\t\t\tu.EndUserAddress = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.SGSNAddressForSignalling == nil {\n\t\t\t\tu.SGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tu.SGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tu.SetLength()\n\treturn u\n}\n\n// Marshal returns the byte sequence generated from a UpdatePDPContextRequest.\nfunc (u *UpdatePDPContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, u.MarshalLen())\n\tif err := u.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (u *UpdatePDPContextRequest) MarshalTo(b []byte) error {\n\tif u.Header.Payload != nil {\n\t\tu.Header.Payload = nil\n\t}\n\tu.Header.Payload = make([]byte, u.MarshalLen()-u.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := u.RAI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelDataI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.EndUserAddress; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(u.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tu.Header.SetLength()\n\treturn u.Header.MarshalTo(b)\n}\n\n// ParseUpdatePDPContextRequest parses a given byte sequence as a UpdatePDPContextRequest.\nfunc ParseUpdatePDPContextRequest(b []byte) (*UpdatePDPContextRequest, error) {\n\tu := &UpdatePDPContextRequest{}\n\tif err := u.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn u, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a UpdatePDPContextRequest.\nfunc (u *UpdatePDPContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tu.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(u.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(u.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tu.RAI = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tu.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tu.FlowLabelSignalling = i\n\t\tcase ie.EndUserAddress:\n\t\t\tu.EndUserAddress = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.SGSNAddressForSignalling == nil {\n\t\t\t\tu.SGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tu.SGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (u *UpdatePDPContextRequest) MarshalLen() int {\n\tl := u.Header.MarshalLen() - len(u.Header.Payload)\n\n\tif ie := u.RAI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.EndUserAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (u *UpdatePDPContextRequest) SetLength() {\n\tu.Header.Length = uint16(u.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (u *UpdatePDPContextRequest) MessageTypeName() string {\n\treturn \"Update PDP Context Request\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (u *UpdatePDPContextRequest) TID() string {\n\treturn u.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/update-pdp-context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes UpdatePDPContextRequest into bytes.\n//\n// Deprecated: use UpdatePDPContextRequest.Marshal instead.\nfunc (u *UpdatePDPContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"UpdatePDPContextRequest.Serialize is deprecated. use UpdatePDPContextRequest.Marshal instead\")\n\treturn u.Marshal()\n}\n\n// SerializeTo serializes UpdatePDPContextRequest into bytes given as b.\n//\n// Deprecated: use UpdatePDPContextRequest.MarshalTo instead.\nfunc (u *UpdatePDPContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"UpdatePDPContextRequest.SerializeTo is deprecated. use UpdatePDPContextRequest.MarshalTo instead\")\n\treturn u.MarshalTo(b)\n}\n\n// DecodeUpdatePDPContextRequest decodes bytes as UpdatePDPContextRequest.\n//\n// Deprecated: use ParseUpdatePDPContextRequest instead.\nfunc DecodeUpdatePDPContextRequest(b []byte) (*UpdatePDPContextRequest, error) {\n\tlog.Println(\"DecodeUpdatePDPContextRequest is deprecated. use ParseUpdatePDPContextRequest instead\")\n\treturn ParseUpdatePDPContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as UpdatePDPContextRequest.\n//\n// Deprecated: use UpdatePDPContextRequest.UnmarshalBinary instead.\nfunc (u *UpdatePDPContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"UpdatePDPContextRequest.DecodeFromBytes is deprecated. use UpdatePDPContextRequest.UnmarshalBinary instead\")\n\treturn u.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of UpdatePDPContextRequest.\n//\n// Deprecated: use UpdatePDPContextRequest.MarshalLen instead.\nfunc (u *UpdatePDPContextRequest) Len() int {\n\tlog.Println(\"UpdatePDPContextRequest.Len is deprecated. use UpdatePDPContextRequest.MarshalLen instead\")\n\treturn u.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/update-pdp-context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestUpdatePDPContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"mandatory-only\",\n\t\t\tStructured: message.NewUpdatePDPContextRequest(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewQualityOfServiceProfile(1, 1, 1, 1, 1),\n\t\t\t\tie.NewFlowLabelDataI(11),\n\t\t\t\tie.NewFlowLabelSignalling(22),\n\t\t\t\tie.NewEndUserAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t\tie.NewGSNAddress(\"3.3.3.3\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x12, 0x00, 0x21,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// QualityOfServiceProfile\n\t\t\t\t0x06, 0x09, 0x11, 0x01,\n\t\t\t\t// FlowLabelDataI\n\t\t\t\t0x10, 0x00, 0x0b,\n\t\t\t\t// FlowLabelSignalling\n\t\t\t\t0x11, 0x00, 0x16,\n\t\t\t\t// EndUserAddress\n\t\t\t\t0x80, 0x00, 0x06, 0xf1, 0x21, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// SGSNAddressForSignalling\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// SGSNAddressForUserData\n\t\t\t\t0x85, 0x00, 0x04, 0x03, 0x03, 0x03, 0x03,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdatePDPContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/message/update-pdp-context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n)\n\n// UpdatePDPContextResponse is a UpdatePDPContextResponse Header and its IEs above.\ntype UpdatePDPContextResponse struct {\n\t*Header\n\tCause                     *ie.IE\n\tQoSProfile                *ie.IE\n\tRecovery                  *ie.IE\n\tFlowLabelDataI            *ie.IE\n\tFlowLabelSignalling       *ie.IE\n\tChargingID                *ie.IE\n\tEndUserAddress            *ie.IE\n\tGGSNAddressForSignalling  *ie.IE\n\tGGSNAddressForUserTraffic *ie.IE\n\tChargingGatewayAddress    *ie.IE\n\tPrivateExtension          *ie.IE\n\tAdditionalIEs             []*ie.IE\n}\n\n// NewUpdatePDPContextResponse creates a new UpdatePDPContextResponse.\nfunc NewUpdatePDPContextResponse(seq, label uint16, tid uint64, ies ...*ie.IE) *UpdatePDPContextResponse {\n\tu := &UpdatePDPContextResponse{\n\t\tHeader: NewHeader(\n\t\t\t0x1e, MsgTypeUpdatePDPContextResponse, seq, label, tid, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tu.Cause = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tu.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tu.FlowLabelSignalling = i\n\t\tcase ie.ChargingID:\n\t\t\tu.ChargingID = i\n\t\tcase ie.EndUserAddress:\n\t\t\tu.EndUserAddress = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.GGSNAddressForSignalling == nil {\n\t\t\t\tu.GGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tu.GGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tu.ChargingGatewayAddress = i\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tu.SetLength()\n\treturn u\n}\n\n// Marshal returns the byte sequence generated from a UpdatePDPContextResponse.\nfunc (u *UpdatePDPContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, u.MarshalLen())\n\tif err := u.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (u *UpdatePDPContextResponse) MarshalTo(b []byte) error {\n\tif u.Header.Payload != nil {\n\t\tu.Header.Payload = nil\n\t}\n\tu.Header.Payload = make([]byte, u.MarshalLen()-u.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := u.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelDataI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingID; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.EndUserAddress; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(u.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tu.Header.SetLength()\n\treturn u.Header.MarshalTo(b)\n}\n\n// ParseUpdatePDPContextResponse parses a given byte sequence as a UpdatePDPContextResponse.\nfunc ParseUpdatePDPContextResponse(b []byte) (*UpdatePDPContextResponse, error) {\n\tu := &UpdatePDPContextResponse{}\n\tif err := u.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn u, nil\n}\n\n// UnmarshalBinary parses a given byte sequence as a UpdatePDPContextResponse.\nfunc (u *UpdatePDPContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tu.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(u.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(u.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tu.Cause = i\n\t\tcase ie.QualityOfServiceProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.FlowLabelDataI:\n\t\t\tu.FlowLabelDataI = i\n\t\tcase ie.FlowLabelSignalling:\n\t\t\tu.FlowLabelSignalling = i\n\t\tcase ie.ChargingID:\n\t\t\tu.ChargingID = i\n\t\tcase ie.EndUserAddress:\n\t\t\tu.EndUserAddress = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.GGSNAddressForSignalling == nil {\n\t\t\t\tu.GGSNAddressForSignalling = i\n\t\t\t} else {\n\t\t\t\tu.GGSNAddressForUserTraffic = i\n\t\t\t}\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tu.ChargingGatewayAddress = i\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (u *UpdatePDPContextResponse) MarshalLen() int {\n\tl := u.Header.MarshalLen() - len(u.Header.Payload)\n\n\tif ie := u.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.FlowLabelSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.EndUserAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (u *UpdatePDPContextResponse) SetLength() {\n\tu.Header.Length = uint16(u.MarshalLen() - 20)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (u *UpdatePDPContextResponse) MessageTypeName() string {\n\treturn \"Update PDP Context Response\"\n}\n\n// TID returns the TID in human-readable string.\nfunc (u *UpdatePDPContextResponse) TID() string {\n\treturn u.tid()\n}\n"
  },
  {
    "path": "gtpv0/message/update-pdp-context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes UpdatePDPContextResponse into bytes.\n//\n// Deprecated: use UpdatePDPContextResponse.Marshal instead.\nfunc (u *UpdatePDPContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"UpdatePDPContextResponse.Serialize is deprecated. use UpdatePDPContextResponse.Marshal instead\")\n\treturn u.Marshal()\n}\n\n// SerializeTo serializes UpdatePDPContextResponse into bytes given as b.\n//\n// Deprecated: use UpdatePDPContextResponse.MarshalTo instead.\nfunc (u *UpdatePDPContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"UpdatePDPContextResponse.SerializeTo is deprecated. use UpdatePDPContextResponse.MarshalTo instead\")\n\treturn u.MarshalTo(b)\n}\n\n// DecodeUpdatePDPContextResponse decodes bytes as UpdatePDPContextResponse.\n//\n// Deprecated: use ParseUpdatePDPContextResponse instead.\nfunc DecodeUpdatePDPContextResponse(b []byte) (*UpdatePDPContextResponse, error) {\n\tlog.Println(\"DecodeUpdatePDPContextResponse is deprecated. use ParseUpdatePDPContextResponse instead\")\n\treturn ParseUpdatePDPContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as UpdatePDPContextResponse.\n//\n// Deprecated: use UpdatePDPContextResponse.UnmarshalBinary instead.\nfunc (u *UpdatePDPContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"UpdatePDPContextResponse.DecodeFromBytes is deprecated. use UpdatePDPContextResponse.UnmarshalBinary instead\")\n\treturn u.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of UpdatePDPContextResponse.\n//\n// Deprecated: use UpdatePDPContextResponse.MarshalLen instead.\nfunc (u *UpdatePDPContextResponse) Len() int {\n\tlog.Println(\"UpdatePDPContextResponse.Len is deprecated. use UpdatePDPContextResponse.MarshalLen instead\")\n\treturn u.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv0/message/update-pdp-context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv0\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/testutils\"\n)\n\nfunc TestUpdatePDPContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"request-accepted\",\n\t\t\tStructured: message.NewUpdatePDPContextResponse(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewCause(gtpv0.CauseRequestAccepted),\n\t\t\t\tie.NewQualityOfServiceProfile(1, 1, 1, 1, 1),\n\t\t\t\tie.NewFlowLabelDataI(11),\n\t\t\t\tie.NewFlowLabelSignalling(22),\n\t\t\t\tie.NewChargingID(0xff),\n\t\t\t\tie.NewEndUserAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t\tie.NewGSNAddress(\"3.3.3.3\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x13, 0x00, 0x28,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x80,\n\t\t\t\t// QualityOfServiceProfile\n\t\t\t\t0x06, 0x09, 0x11, 0x01,\n\t\t\t\t// FlowLabelDataI\n\t\t\t\t0x10, 0x00, 0x0b,\n\t\t\t\t// FlowLabelSignalling\n\t\t\t\t0x11, 0x00, 0x16,\n\t\t\t\t// ChargingID\n\t\t\t\t0x7f, 0x00, 0x00, 0x00, 0xff,\n\t\t\t\t// EndUserAddress\n\t\t\t\t0x80, 0x00, 0x06, 0xf1, 0x21, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// GGSNAddressForSignalling\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// GGSNAddressForUserData\n\t\t\t\t0x85, 0x00, 0x04, 0x03, 0x03, 0x03, 0x03,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"no-resources\",\n\t\t\tStructured: message.NewUpdatePDPContextResponse(\n\t\t\t\ttestutils.TestFlow.Seq, testutils.TestFlow.Label, testutils.TestFlow.TID,\n\t\t\t\tie.NewCause(gtpv0.CauseNoResourcesAvailable),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x1e, 0x13, 0x00, 0x02,\n\t\t\t\t// SequenceNumber\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Sndpd\n\t\t\t\t0xff, 0xff, 0xff, 0xff,\n\t\t\t\t// TID\n\t\t\t\t0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x55,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0xc7,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdatePDPContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv0/testutils/testutils.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package testutils is an internal package to be used for unit tests. Don't use this.\npackage testutils\n\nimport (\n\t\"testing\"\n\n\t\"github.com/pascaldekloe/goe/verify\"\n\t\"github.com/wmnsk/go-gtp/gtpv0/message\"\n)\n\n// Serializable is just for testing gtpv2.Messages. Don't use this.\ntype Serializable interface {\n\tMarshal() ([]byte, error)\n\tMarshalLen() int\n}\n\n// TestCase is just for testing gtpv2.Messages. Don't use this.\ntype TestCase struct {\n\tDescription string\n\tStructured  Serializable\n\tSerialized  []byte\n}\n\n// ParseFunc is just for testing gtpv2.Messages. Don't use this.\ntype ParseFunc func([]byte) (Serializable, error)\n\n// TestFlow is just for testing gtpv2.Messages. Don't use this.\nvar TestFlow = struct {\n\tSeq, Label uint16\n\tTID        uint64\n}{\n\t0x0001, 0x0000, 0x2143658709214355,\n}\n\n// Run is just for testing gtpv2.Messages. Don't use this.\nfunc Run(t *testing.T, cases []TestCase, parse ParseFunc) {\n\tt.Helper()\n\n\tfor _, c := range cases {\n\t\tt.Run(c.Description, func(t *testing.T) {\n\t\t\tt.Run(\"Parse\", func(t *testing.T) {\n\t\t\t\tv, err := parse(c.Serialized)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := v, c.Structured; !verify.Values(t, \"\", got, want) {\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Marshal\", func(t *testing.T) {\n\t\t\t\tb, err := c.Structured.Marshal()\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := b, c.Serialized; !verify.Values(t, \"\", got, want) {\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Len\", func(t *testing.T) {\n\t\t\t\tif got, want := c.Structured.MarshalLen(), len(c.Serialized); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Interface\", func(t *testing.T) {\n\t\t\t\t// Ignore *Header and Generic in this tests.\n\t\t\t\tif _, ok := c.Structured.(*message.Header); ok {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif _, ok := c.Structured.(*message.Generic); ok {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tParsed, err := message.Parse(c.Serialized)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := Parsed.Version(), c.Structured.(message.Message).Version(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := Parsed.MessageType(), c.Structured.(message.Message).MessageType(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := Parsed.MessageTypeName(), c.Structured.(message.Message).MessageTypeName(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := Parsed.TID(), c.Structured.(message.Message).TID(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv1/README.md",
    "content": "# v1: GTPv1 in Golang\n\nPackage v1 provides simple and painless handling of GTPv1-C and GTPv1-U protocols in pure Golang.\n\n## Getting Started\n\nThis package is still under construction. The networking feature is only available for GTPv1-U. GTPv1-C feature would be available in the future.  \nSee message and ie directory for what you can do with the current implementation. \n\n### Creating a PDP Context as a client\n\n_NOT IMPLEMENTED YET!_\n\n### Waiting for a PDP Context to be created as a server\n\n_NOT IMPLEMENTED YET!_\n\n### Opening a U-Plane connection\n\nRetrieve `UPlaneConn` first, using `DialUPlane` (for client) or `NewUPlaneConn` (for server). \n\n#### Client\n\n`DialUPlane` sends Echo Request and returns `UPlaneConn` if it succeeds.\nIf you don't need Echo, see Server section. As GTP is UDP-based connection, and there are no session management on `UPlaneConn`, the behavior of `Dial` and `ListenAndServe` is not quite different.\n\n```go\nuConn, err := v1.Dial(ctx, laddr, raddr)\nif err != nil {\n\t// ...\n}\ndefer uConn.Close()\n```\n\n#### Server\n\nRetrieve `UPlaneConn` with `NewUPlaneConn`, and `ListenAndServe` to start listening.\n\n```go\nuConn := v1.NewUPlaneConn(laddr)\nif err != nil {\n\t// ...\n}\ndefer uConn.Close()\n\n// This blocks, and returns an error when it's fatal.\nif err := uConn.ListenAndServe(ctx); err != nil {\n\t// ...\n}\n```\n\n### Manupulating `UPlaneConn`\n\nWith `UPlaneConn`, you can add and delete tunnels, and manipulate device directly.\n\n#### Using Linux Kernel GTP-U\n\nLinux Kernel GTP-U is quite performant and easy to handle, but it requires root privilege, and of course it works only on Linux. So it is disabled by default. To get started, enable it first. Note that it cannot be disabled while the program is working.\n\n```go\nif err := uConn.EnableKernelGTP(\"gtp0\", v1.roleSGSN); err != nil {\n\t// ...\n}\n```\n\nThen, when the bearer information is ready, use `AddTunnel` or `AddTunnelOverride` to add a tunnel.  \nThe latter one deletes the existing tunnel with the same IP and/or incoming TEID before creating a tunnel,\nwhile the former fails if there's any duplication.\n\n```go\n// add a tunnel by giving GTP peer's IP, subscriber's IP,\nif err := uConn.AddTunnelOverride(\n\tnet.ParseIP(\"10.10.10.10\"), // GTP peer's IP\n\tnet.ParseIP(\"1.1.1.1\"),     // subscriber's IP\n\t0x55667788,                 // outgoing TEID\n\t0x11223344,                 // incoming TEID\n); err != nil {\n\t// ...\n}\n```\n\nWhen the tunnel is no longer necessary, use `DelTunnelByITEI` or `DelTunnelByMSAddress` to delete it.  \nOr, by `Close`-ing the `UPlaneConn`, all the tunnels associated will the cleared.\n\n```go\n// delete a tunnel by giving an incoming TEID.\nif err := uConn.DelTunnelByITEI(0x11223344); err != nil {\n\t// ...\n}\n\n// delete a tunnel by giving an IP address assigned to a subscriber.\nif err := uConn.DelTunnelByMSAddress(net.ParseIP(\"1.1.1.1\")); err != nil {\n\t// ...\n}\n```\n\nThe packets NOT forwarded by the Kernel can be handled automatically by giving a handler to `UPlaneConn`.  \nHandlers for T-PDU, Echo Request/Response, and Error Indication are registered by default, but you can override them using `AddHandler`.\n\n```go\nuConn.AddHandler(message.MsgTypeEchoRequest, func(c v1.Conn, senderAddr net.Addr, msg message.Message) error {\n\t// do anything you want for Echo Request here.\n\t// errors returned here are passed to `errCh` that is given to UPlaneConn at the beginning.\n\treturn nil\n})\n```\n\nIf the tunnel with appropriate IP or TEID is not found for a T-PDU packet, Kernel sends it to userland. You can manipulate it with `ReadFromGTP`.\n\n```go\nbuf := make([]byte, 1500)\n\n// the 3rd returned value is TEID in GTPv1-U Header.\nn, raddr, teid, err := uConn.ReadFromGTP(buf)\nif err != nil {\n\t// ...\n}\n\nfmt.Printf(\"%x\", buf[:n]) // prints only the payload, no GTP header included.\n```\n\nAlso, you can send any payload by using `WriteToGTP`. It writes the given payload with GTP header to the specified addr over `UPlaneConn`.\n\n```go\n// first return value is the number of bytes written.\nif _, err := uConn.WriteToGTP(teid, payload, addr); err != nil {\n\t// ...\n}\n```\n\n#### Using userland GTP-U\n\n**Note:** _package v1 does provide the encapsulation/decapsulation and some networking features, but it does NOT provide routing of the decapsulated packets, nor capturing IP layer and above on the specified interface. This is because such kind of operations cannot be done without platform-specific codes._\n\nYou can use to `ReadFromGTP` read the packets coming into uConn. This does not work for the packets which are handled by `RelayTo`.\n\n```go\nbuf := make([]byte, 1500)\nn, raddr, teid, err := uConn.ReadFromGTP(buf)\nif err != nil {\n\t// ...\n}\n\nfmt.Printf(\"%x\", buf[:n]) // prints the payload encapsulated in the GTP header.\n```\n\nAlso, you can send any payload by using `WriteToGTP`. It writes the given payload with GTP header to the specified addr over `UPlaneConn`.\n\n```go\n// first return value is the number of bytes written.\nif _, err := uConn.WriteToGTP(teid, payload, addr); err != nil {\n\t// ...\n}\n```\n\nEspecially or SGSN/S-GW-ish nodes(=have multiple GTP tunnels and its raison d'être is just to forward traffic right to left/left to right) we provide a method to swap TEID and forward T-PDU packets automatically and efficiently.  \nBy using `RelayTo`, the `UPlaneConn` automatically handles the T-PDU packet in background with the least cost. Note that it's performed on the userland and thus it's not so performant.\n\n```go\n// this is the example for S-GW that completed establishing a session and ready to forward U-Plane packets.\ns1uConn.RelayTo(s5uConn, s1usgwTEID, s5uBearer.OutgoingTEID, s5uBearer.RemoteAddress)\ns5uConn.RelayTo(s1uConn, s5usgwTEID, s1uBearer.OutgoingTEID, s1uBearer.RemoteAddress)\n```\n\n### Handling Extension Headers\n\n`AddExtensionHeaders` adds ExtensionHeader(s) to the Header of a Message, set the E flag, and checks if the types given are consistent (error will be returned if not).\n\n```go\nmsg := message.NewTPDU(0x11223344, []byte{0xde, 0xad, 0xbe, 0xef})\nif err := msg.AddExtensionHeaders(\n\t// We don't support construction of the specific type of an ExtensionHeader.\n\t// The second parameter should be the serialized bytes of contents.\n\tmessage.NewExtensionHeader(\n\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t[]byte{0x22, 0xb8},\n\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t),\n\tmessage.NewExtensionHeader(\n\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t\t[]byte{0x00, 0xc2},\n\t\tmessage.ExtHeaderTypeNoMoreExtensionHeaders,\n\t),\n); err != nil {\n\t// ...\n}\n```\n\nExtensionHeaders decoded or added are stored in `ExtensionHeaders` field in the Header, which can be accessed like this.\n\n```go\n// no need to write msg.Header.ExtensionHeaders, as the Header is embedded in messages.\nfor _, eh := range msg.ExtensionHeaders {\n\tlog.Println(eh.Type)     // ExtensionHeader type has its own Type while it's not actually included in a packet. \n\tlog.Println(eh.Content)  // We do not support decoding of each type of content yet. Decode them on your own.\n\tlog.Println(eh.NextType) // Don't sort the slice - it ruins the packet, or even cause a panic.\n}\n```\n\nWhen you are directly manipulating a Header for some reason, `WithExtensionHeaders` would help you simplify your operation.\nBe sure not to call it on a Message, as it returns `*Header`, not a `Message` interface.\n\n```go\nheader := message.NewHeader(\n\t0x30, // no need to set E flag here - With... method will do that instead.\n\tmessage.MsgTypeEchoRequest,\n\t0xdeadbeef,\n\t0x00,\n\t[]byte{0xde, 0xad, 0xbe, 0xef},\n).WithExtensionHeaders(\n\tmessage.NewExtensionHeader(\n\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t[]byte{0x22, 0xb8},\n\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t),\n\tmessage.NewExtensionHeader(\n\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t\t[]byte{0x00, 0xc2},\n\t\tmessage.ExtHeaderTypeNoMoreExtensionHeaders,\n\t),\n)\n```\n\n## Supported Features\n\n### Messages\n\nThe following Messages marked with \"Yes\" are currently available with their own useful constructors.\n\n_Even there are some missing Messages, you can create any kind of Message by using `message.NewGeneric`._\n\n| ID        | Name                                        | Supported |\n|-----------|---------------------------------------------|-----------|\n| 0         | (Spare/Reserved)                            | -         |\n| 1         | Echo Request                                | Yes       |\n| 2         | Echo Response                               | Yes       |\n| 3         | Version Not Supported                       | Yes       |\n| 4         | Node Alive Request                          |           |\n| 5         | Node Alive Response                         |           |\n| 6         | Redirection Request                         |           |\n| 7         | Redirection Response                        |           |\n| 8-15      | (Spare/Reserved)                            | -         |\n| 16        | Create PDP Context Request                  | Yes       |\n| 17        | Create PDP Context Response                 | Yes       |\n| 18        | Update PDP Context Request                  | Yes       |\n| 19        | Update PDP Context Response                 | Yes       |\n| 20        | Delete PDP Context Request                  | Yes       |\n| 21        | Delete PDP Context Response                 | Yes       |\n| 22        | Initiate PDP Context Activation Request     |           |\n| 23        | Initiate PDP Context Activation Response    |           |\n| 24-25     | (Spare/Reserved)                            | -         |\n| 26        | Error Indication                            | Yes       |\n| 27        | PDU Notification Request                    |           |\n| 28        | PDU Notification Response                   |           |\n| 29        | PDU Notification Reject Request             |           |\n| 30        | PDU Notification Reject Response            |           |\n| 31        | Supported Extension Headers Notification    | Yes       |\n| 32        | Send Routeing Information for GPRS Request  |           |\n| 33        | Send Routeing Information for GPRS Response |           |\n| 34        | Failure Report Request                      |           |\n| 35        | Failure Report Response                     |           |\n| 36        | Note MS GPRS Present Request                |           |\n| 37        | Note MS GPRS Present Response               |           |\n| 38-47     | (Spare/Reserved)                            | -         |\n| 48        | Identification Request                      |           |\n| 49        | Identification Response                     |           |\n| 50        | SGSN Context Request                        |           |\n| 51        | SGSN Context Response                       |           |\n| 52        | SGSN Context Acknowledge                    |           |\n| 53        | Forward Relocation Request                  |           |\n| 54        | Forward Relocation Response                 |           |\n| 55        | Forward Relocation Complete                 |           |\n| 56        | Relocation Cancel Request                   |           |\n| 57        | Relocation Cancel Response                  |           |\n| 58        | Forward SRNS Context                        |           |\n| 59        | Forward Relocation Complete Acknowledge     |           |\n| 60        | Forward SRNS Context Acknowledge            |           |\n| 61        | UE Registration Query Request               |           |\n| 62        | UE Registration Query Response              |           |\n| 63-69     | (Spare/Reserved)                            | -         |\n| 70        | RAN Information Relay                       |           |\n| 71-95     | (Spare/Reserved)                            | -         |\n| 96        | MBMS Notification Request                   |           |\n| 97        | MBMS Notification Response                  |           |\n| 98        | MBMS Notification Reject Request            |           |\n| 99        | MBMS Notification Reject Response           |           |\n| 100       | Create MBMS Context Request                 |           |\n| 101       | Create MBMS Context Response                |           |\n| 102       | Update MBMS Context Request                 |           |\n| 103       | Update MBMS Context Response                |           |\n| 104       | Delete MBMS Context Request                 |           |\n| 105       | Delete MBMS Context Response                |           |\n| 106 - 111 | (Spare/Reserved)                            | -         |\n| 112       | MBMS Registration Request                   |           |\n| 113       | MBMS Registration Response                  |           |\n| 114       | MBMS De-Registration Request                |           |\n| 115       | MBMS De-Registration Response               |           |\n| 116       | MBMS Session Start Request                  |           |\n| 117       | MBMS Session Start Response                 |           |\n| 118       | MBMS Session Stop Request                   |           |\n| 119       | MBMS Session Stop Response                  |           |\n| 120       | MBMS Session Update Request                 |           |\n| 121       | MBMS Session Update Response                |           |\n| 122-127   | (Spare/Reserved)                            | -         |\n| 128       | MS Info Change Notification Request         |           |\n| 129       | MS Info Change Notification Response        |           |\n| 130-239   | (Spare/Reserved)                            | -         |\n| 240       | Data Record Transfer Request                |           |\n| 241       | Data Record Transfer Response               |           |\n| 242-253   | (Spare/Reserved)                            | -         |\n| 254       | End Marker                                  |           |\n| 255       | G-PDU                                       | Yes       |\n\n### Information Elements\n\nThe following Information Elements marked with \"Yes\" are currently supported with their own useful constructors.\n\n_Even there are some missing IEs, you can create any kind of IEs by using `ie.New` function or by initializing ie.IE directly._\n\n| ID      | Name                                      | Supported |\n|---------|-------------------------------------------|-----------|\n| 0       | (Spare/Reserved)                          | -         |\n| 1       | Cause                                     | Yes       |\n| 2       | IMSI                                      | Yes       |\n| 3       | Routeing Area Identity                    | Yes       |\n| 4       | Temporary Logical Link Identity           |           |\n| 5       | Packet TMSI                               | Yes       |\n| 6       | (Spare/Reserved)                          | -         |\n| 7       | (Spare/Reserved)                          | -         |\n| 8       | Reordering Required                       | Yes       |\n| 9       | Authentication Triplet                    | Yes       |\n| 10      | (Spare/Reserved)                          | -         |\n| 11      | MAP Cause                                 | Yes       |\n| 12      | P-TMSI Signature                          | Yes       |\n| 13      | MS Validated                              | Yes       |\n| 14      | Recovery                                  | Yes       |\n| 15      | Selection Mode                            | Yes       |\n| 16      | TEID Data I                               | Yes       |\n| 17      | TEID C-Plane                              | Yes       |\n| 18      | TEID Data II                              | Yes       |\n| 19      | Teardown Indication                       | Yes       |\n| 20      | NSAPI                                     | Yes       |\n| 21      | RANAP Cause                               | Yes       |\n| 22      | RAB Context                               |           |\n| 23      | Radio Priority SMS                        |           |\n| 24      | Radio Priority                            |           |\n| 25      | Packet Flow ID                            |           |\n| 26      | Charging Characteristics                  |           |\n| 27      | Trace Reference                           |           |\n| 28      | Trace Type                                |           |\n| 29      | MS Not Reachable Reason                   |           |\n| 30-126  | (Spare/Reserved)                          | -         |\n| 127     | Charging ID                               | Yes       |\n| 128     | End User Address                          | Yes       |\n| 129     | MM Context                                |           |\n| 130     | PDP Context                               |           |\n| 131     | Access Point Name                         | Yes       |\n| 132     | Protocol Configuration Options            | Yes       |\n| 133     | GSN Address                               | Yes       |\n| 134     | MSISDN                                    | Yes       |\n| 135     | QoS Profile                               |           |\n| 136     | Authentication Quintuplet                 | Yes       |\n| 137     | Traffic Flow Template                     |           |\n| 138     | Target Identification                     |           |\n| 139     | UTRAN Transparent Container               |           |\n| 140     | RAB Setup Information                     |           |\n| 141     | Extension Header Type List                | Yes       |\n| 142     | Trigger Id                                |           |\n| 143     | OMC Identity                              |           |\n| 144     | RAN Transparent Container                 |           |\n| 145     | PDP Context Prioritization                |           |\n| 146     | Additional RAB Setup Information          |           |\n| 147     | SGSN Number                               |           |\n| 148     | Common Flags                              | Yes       |\n| 149     | APN Restriction                           | Yes       |\n| 150     | Radio Priority LCS                        |           |\n| 151     | RAT Type                                  | Yes       |\n| 152     | User Location Information                 | Yes       |\n| 153     | MS Time Zone                              | Yes       |\n| 154     | IMEISV                                    | Yes       |\n| 155     | CAMEL Charging Information Container      |           |\n| 156     | MBMS UE Context                           |           |\n| 157     | Temporary Mobile Group Identity           |           |\n| 158     | RIM Routing Address                       |           |\n| 159     | MBMS Protocol Configuration Options       |           |\n| 160     | MBMS Service Area                         |           |\n| 161     | Source RNC PDCP Context Info              |           |\n| 162     | Additional Trace Info                     |           |\n| 163     | Hop Counter                               |           |\n| 164     | Selected PLMN Id                          |           |\n| 165     | MBMS Session Identifier                   |           |\n| 166     | MBMS 2G/3G Indicator                      |           |\n| 167     | Enhanced NSAPI                            |           |\n| 168     | MBMS Session Duration                     |           |\n| 169     | Additional MBMS Trace Info                |           |\n| 170     | MBMS Session Repetition Number            |           |\n| 171     | MBMS Time To Data Transfer                |           |\n| 172     | (Spare/Reserved)                          | -         |\n| 173     | BSS Container                             |           |\n| 174     | Cell Identification                       |           |\n| 175     | PDU Numbers                               |           |\n| 176     | BSS GP Cause                              |           |\n| 177     | Required MBMS Bearer Capabilities         |           |\n| 178     | RIM Routing Address Discriminator         |           |\n| 179     | List of Setup PFCs                        |           |\n| 180     | PS Handover XID Parameters                |           |\n| 181     | MS Info Change Reporting Action           |           |\n| 182     | Direct Tunnel Flags                       |           |\n| 183     | Correlation Id                            |           |\n| 184     | Bearer Control Mode                       |           |\n| 185     | MBMS Flow Identifier                      |           |\n| 186     | MBMS IP Multicast Distribution            |           |\n| 187     | MBMS Distribution Acknowledgement         |           |\n| 188     | Reliable InterRAT Handover Info           |           |\n| 189     | RFSP Index                                |           |\n| 190     | Fully Qualified Domain Name               |           |\n| 191     | Evolved Allocation Retention Priority I   |           |\n| 192     | Evolved Allocation Retention Priority II  |           |\n| 193     | Extended Common Flags                     | Yes       |\n| 194     | User CSG Information                      |           |\n| 195     | CSG Information Reporting Action          |           |\n| 196     | CSG ID                                    |           |\n| 197     | CSG Membership Indication                 |           |\n| 198     | Aggregate Maximum Bit Rate                |           |\n| 199     | UE Network Capability                     |           |\n| 200     | UE-AMBR                                   |           |\n| 201     | APN-AMBR with NSAPI                       |           |\n| 202     | GGSN Back-Off Time                        |           |\n| 203     | Signalling Priority Indication            |           |\n| 204     | Signalling Priority Indication with NSAPI |           |\n| 205     | Higher Bitrates than 16Mbps Flag          |           |\n| 206     | (Spare/Reserved)                          | -         |\n| 207     | Additional MM Context for SRVCC           |           |\n| 208     | Additional Flags for SRVCC                |           |\n| 209     | STN-SR                                    |           |\n| 210     | C-MSISDN                                  |           |\n| 211     | Extended RANAP Cause                      |           |\n| 212     | eNodeB ID                                 |           |\n| 213     | Selection Mode with NSAPI                 |           |\n| 214     | ULI Timestamp                             | Yes       |\n| 215     | LHN Id with NSAPI                         |           |\n| 216     | CN Operator Selection Entity              |           |\n| 217     | UE Usage Type                             |           |\n| 218     | Extended Common Flags II                  | Yes       |\n| 219     | Node Identifier                           |           |\n| 220     | CIoT Optimizations Support Indication     |           |\n| 221     | SCEF PDN Connection                       |           |\n| 222     | IOV Updates Counter                       |           |\n| 223-237 | (Spare/Reserved)                          | -         |\n| 238     | Special IE Type for IE Type Extension     |           |\n| 239-250 | (Spare/Reserved)                          | -         |\n| 251     | Charging Gateway Address                  |           |\n| 252-254 | (Spare/Reserved)                          | -         |\n| 255     | Private Extension                         |           |\n"
  },
  {
    "path": "gtpv1/conn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"net\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n)\n\n// Conn is an abstraction of both GTPv1-C and GTPv1-U Conn.\ntype Conn interface {\n\tnet.PacketConn\n\tAddHandler(uint8, HandlerFunc)\n\tRespondTo(net.Addr, message.Message, message.Message) error\n\tRestarts() uint8\n}\n"
  },
  {
    "path": "gtpv1/constants.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\n// Registered UDP ports\nconst (\n\tGTPCPort = \":2123\"\n\tGTPUPort = \":2152\"\n)\n\n// Cause definitions.\nconst (\n\tReqCauseRequestIMSI uint8 = iota\n\tReqCauseRequestIMEI\n\tReqCauseRequestIMSIAndIMEI\n\tReqCauseNoIdentityNeeded\n\tReqCauseMSRefuses\n\tReqCauseMSIsNotGPRSResponding\n\tReqCauseReactivationRequested\n\tReqCausePDPAddressInactivityTimerExpires\n\tReqCauseNetworkFailure\n\tReqCauseQoSParameterMismatch\n\t// 10-127: for future use / reserved for prime\n)\n\n// Cause definitions.\nconst (\n\tResCauseRequestAccepted uint8 = iota + 128\n\tResCauseNewPDPTypeDueToNetworkPreference\n\tResCauseNewPDPTypeDueToSingleAddressBearerOnly\n\t// 131-191: for future use / reserved for prime.\n)\n\n// Cause definitions.\nconst (\n\tResCauseNonExistent uint8 = iota + 192\n\tResCauseInvalidMessageFormat\n\tResCauseIMSIIMEINotKnown\n\tResCauseMSIsGPRSDetached\n\tResCauseMSIsNotGPRSResponding\n\tResCauseMSRefuses\n\tResCauseVersionNotSupported\n\tResCauseNoResourcesAvailable\n\tResCauseServiceNotSupported\n\tResCauseMandatoryIEIncorrect\n\tResCauseMandatoryIEMissing\n\tResCauseOptionalIEIncorrect\n\tResCauseSystemFailure\n\tResCauseRoamingRestriction\n\tResCausePTMSISignatureMismatch\n\tResCauseGPRSConnectionSuspended\n\tResCauseAuthenticationFailure\n\tResCauseUserAuthenticationFailed\n\tResCauseContextNotFound\n\tResCauseAllDynamicPDPAddressesAreOccupied\n\tResCauseNoMemoryIsAvailable\n\tResCauseRelocationFailure\n\tResCauseUnknownMandatoryExtensionHeader\n\tResCauseSemanticErrorInTheTFTOperation\n\tResCauseSyntacticErrorInTheTFTOperation\n\tResCauseSemanticErrorsInPacketFilter\n\tResCauseSyntacticErrorsInPacketFilter\n\tResCauseMissingOrUnknownAPN\n\tResCauseUnknownPDPAddressOrPDPType\n\tResCausePDPContextWithoutTFTAlreadyActivated\n\tResCauseAPNAccessDeniedNoSubscription\n\tResCauseAPNRestrictionTypeIncompatibilityWithCurrentlyActivePDPContexts\n\tResCauseMSMBMSCapabilitiesInsufficient\n\tResCauseInvalidCorrelationID\n\tResCauseMBMSBearerContextSuperseded\n\tResCauseBearerControlModeViolation\n\tResCauseCollisionWithNetworkInitiatedRequest\n\tResCauseAPNCongestion\n\tResCauseBearerHandlingNotSupported\n\tResCauseTargetAccessRestrictedForTheSubscriber\n\tResCauseUEIsTemporarilyNotReachableDueToPowerSaving\n\tResCauseRelocationFailureDueToNASMessageRedirection\n\t// 234-255: for future use / reserved for prime.\n)\n\n// SelectionMode definitions.\nconst (\n\tSelectionModeMSorNetworkProvidedAPNSubscribedVerified uint8 = iota | 0xf0\n\tSelectionModeMSProvidedAPNSubscriptionNotVerified\n\tSelectionModeNetworkProvidedAPNSubscriptionNotVerified\n)\n\n// PDP Type Organization definitions.\nconst (\n\tPDPTypeETSI uint8 = iota | 0xf0\n\tPDPTypeIETF\n)\n\n// Protocol ID definitions.\n// For more identifiers, see RFC 3232.\nconst (\n\tProtoIDLCP  uint16 = 0xc021\n\tProtoIDPAP  uint16 = 0xc023\n\tProtoIDCHAP uint16 = 0xc223\n\tProtoIDIPCP uint16 = 0x8021\n)\n\n// Container ID definitions.\nconst (\n\t_ uint16 = iota\n\tContIDPCSCFIPv6AddressRequest\n\tContIDIMCNSubsystemSignalingFlag\n\tContIDDNSServerIPv6AddressRequest\n\tContIDNotSupported\n\tContIDMSSupportofNetworkRequestedBearerControlIndicator\n\t_\n\tContIDDSMIPv6HomeAgentAddressRequest\n\tContIDDSMIPv6HomeNetworkPrefixRequest\n\tContIDDSMIPv6IPv4HomeAgentAddressRequest\n\tContIDIPaddressAllocationViaNASSignalling\n\tContIDIPv4addressAllocationViaDHCPv4\n\tContIDPCSCFIPv4AddressRequest\n\tContIDDNSServerIPv4AddressRequest\n\tContIDMSISDNRequest\n\tContIDIFOMSupportRequest\n\tContIDIPv4LinkMTURequest\n\tContIDMSSupportOfLocalAddressInTFTIndicator\n\tContIDPCSCFReselectionSupport\n\tContIDNBIFOMRequestIndicator\n\tContIDNBIFOMMode\n\tContIDNonIPLinkMTURequest\n\tContIDAPNRateControlSupportIndicator\n\tContID3GPPPSDataOffUEStatus\n\tContIDReliableDataServiceRequestIndicator\n\tContIDAdditionalAPNRateControlForExceptionDataSupportIndicator\n\tContIDPDUSessionID\n\t_\n\t_\n\t_\n\t_\n\t_\n\tContIDEthernetFramePayloadMTURequest\n\tContIDUnstructuredLinkMTURequest\n\tContID5GSMCauseValue\n)\n\n// Configuration Protocol definitions.\nconst (\n\tConfigProtocolPPPWithIP uint8 = 0\n)\n\n// RATType definitions.\nconst (\n\t_ uint8 = iota\n\tRatTypeUTRAN\n\tRatTypeGERAN\n\tRatTypeWLAN\n\tRatTypeGAN\n\tRatTypeHSPAEvolution\n\tRatTypeEUTRAN\n)\n\n// UserLocationInformation GeographicLocationType definitions.\nconst (\n\tLocTypeCGI uint8 = iota\n\tLocTypeSAI\n\tLocTypeRAI\n)\n\n// APN Restriction definitions.\nconst (\n\tAPNRestrictionNoExistingContextsorRestriction uint8 = iota\n\tAPNRestrictionPublic1\n\tAPNRestrictionPublic2\n\tAPNRestrictionPrivate1\n\tAPNRestrictionPrivate2\n)\n\n// MAP Cause definitions.\nconst (\n\t_ uint8 = iota\n\tMAPCauseUnknownSubscriber\n\tMAPCauseUnknownBaseStation\n\tMAPCauseUnknownMSC\n\tMAPCauseSecureTransportError\n\tMAPCauseUnidentifiedSubscriber\n\tMAPCauseAbsentSubscriberSM\n\tMAPCauseUnknownEquipment\n\tMAPCauseRoamingNotAllowed\n\tMAPCauseIllegalSubscriber\n\tMAPCauseBearerServiceNotProvisioned\n\tMAPCauseTeleserviceNotProvisioned\n\tMAPCauseIllegalEquipment\n\tMAPCauseCallBarred\n\tMAPCauseForwardingViolation\n\tMAPCauseCUGReject\n\tMAPCauseIllegalSSOperation\n\tMAPCauseSSErrorStatus\n\tMAPCauseSSNotAvailable\n\tMAPCauseSSSubscriptionViolatio\n\tMAPCauseSSIncompatibility\n\tMAPCauseFacilityNotSupported\n\tMAPCauseOngoingGroupCall\n\tMAPCauseInvalidTargetBaseStation\n\tMAPCauseNoRadioResourceAvailable\n\tMAPCauseNoHandoverNumberAvailable\n\tMAPCauseSubsequentHandoverFailure\n\tMAPCauseAbsentSubscriber\n\tMAPCauseIncompatibleTerminal\n\tMAPCauseShortTermDenial\n\tMAPCauseLongTermDenial\n\tMAPCauseSubscriberBusyForMTSMS\n\tMAPCauseSMDeliveryFailure\n\tMAPCauseMessageWaitingListFull\n\tMAPCauseSystemFailure\n\tMAPCauseDataMissing\n\tMAPCauseUnexpectedDataValue\n\tMAPCausePWRegistrationFailure\n\tMAPCauseNegativePWCheck\n\tMAPCauseNoRoamingNumberAvailable\n\tMAPCauseTracingBufferFull\n\t_\n\tMAPCauseTargetCellOutsideGroupCallArea\n\tMAPCauseNumberOfPWAttemptsViolation\n\tMAPCauseNumberChanged\n\tMAPCauseBusySubscriber\n\tMAPCauseNoSubscriberReply\n\tMAPCauseForwardingFailed\n\tMAPCauseORNotAllowed\n\tMAPCauseATINotAllowed\n\tMAPCauseNoGroupCallNumberAvailable\n\tMAPCauseResourceLimitation\n\tMAPCauseUnauthorizedRequestingNetwork\n\tMAPCauseUnauthorizedLCSClient\n\tMAPCausePositionMethodFailure\n\t_\n\t_\n\t_\n\tMAPCauseUnknownOrUnreachableLCSClient\n\tMAPCauseMMEventNotSupported\n\tMAPCauseATSINotAllowed\n\tMAPCauseATMNotAllowed\n\tMAPCauseInformationNotAvailabl\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tMAPCauseUnknownAlphabe\n\tMAPCauseUSSDBusy\n)\n\n// RANAP Cause definitions.\nconst (\n\t_ uint8 = iota\n\tRABPreempted\n\tRANAPCauseTrelocoverallExpiry\n\tRANAPCauseTrelocprepExpiry\n\tRANAPCauseTreloccompleteExpiry\n\tRANAPCauseTqueuingExpiry\n\tRANAPCauseRelocationTriggered\n\tRANAPCauseTRELOCallocExpiry\n\tRANAPCauseUnableToEstablishDuringRelocation\n\tRANAPCauseUnknownTargetRNC\n\tRANAPCauseRelocationCancelled\n\tRANAPCauseSuccessfulRelocation\n\tRANAPCauseRequestedCipheringIntegrityProtectionAlgorithmsNotSupported\n\tRANAPCauseChangeOfCipheringIntegrityProtectionIsNotSupported\n\tRANAPCauseFailureInTheRadioInterfaceProcedure\n\tRANAPCauseReleaseDueToUTRANGeneratedReason\n\tRANAPCauseUserInactivity\n\tRANAPCauseTimeCriticalRelocation\n\tRANAPCauseRequestedTrafficClassNotAvailable\n\tRANAPCauseInvalidRABParametersValue\n\tRANAPCauseRequestedMaximumBitRateNotAvailable\n\tRANAPCauseRequestedGuaranteedBitRateNotAvailable\n\tRANAPCauseRequestedTransferDelayNotAchievable\n\tRANAPCauseInvalidRABParametersCombination\n\tRANAPCauseConditionViolationForSDUParameters\n\tRANAPCauseConditionViolationForTrafficHandlingPriority\n\tRANAPCauseConditionViolationForGuaranteedBitRate\n\tRANAPCauseUserPlaneVersionsNotSupported\n\tRANAPCauseIuUPFailure\n\tRANAPCauseRelocationFailureInTargetCNRNCOrTargetSystem\n\tRANAPCauseInvalidRABID\n\tRANAPCauseNoRemainingRAB\n\tRANAPCauseInteractionWithOtherProcedure\n\tRANAPCauseRequestedMaximumBitRateForDLNotAvailable\n\tRANAPCauseRequestedMaximumBitRateForULNotAvailable\n\tRANAPCauseRequestedGuaranteedBitRateForDLNotAvailable\n\tRANAPCauseRequestedGuaranteedBitRateForULNotAvailable\n\tRANAPCauseRepeatedIntegrityCheckingFailure\n\tRANAPCauseRequestedReportTypeNotSupported\n\tRANAPCauseRequestSuperseded\n\tRANAPCauseReleaseDueToUEWenRatedSignallingConnectionRelease\n\tRANAPCauseResourceOptimisationRelocation\n\tRANAPCauseRequestedInformationNotAvailable\n\tRANAPCauseRelocationDesirableForRadioReasons\n\tRANAPCauseRelocationNotSupportedInTargetRNCOrTargetSystem\n\tRANAPCauseDirectedRetry\n\tRANAPCauseRadioConnectionWithUELost\n\tRANAPCauseRNCUnableToEstablishAllRFCs\n\tRANAPCauseDecipheringKeysNotAvailable\n\tRANAPCauseDedicatedAssistanceDataNotAvailable\n\tRANAPCauseRelocationTargetNotAllowed\n\tRANAPCauseLocationReportingCongestion\n\tRANAPCauseReduceLoadInServingCell\n\tRANAPCauseNoRadioResourcesAvailableInTargetCell\n\tRANAPCauseGERANIuModeFailure\n\tRANAPCauseAccessRestrictedDueToSharedNetworks\n\tRANAPCauseIncomingRelocationNotSupportedDueTodPUESBINEFeature\n\tRANAPCauseTrafficLoadInTheTargetCellHigherThanInTheSourceCell\n\tRANAPCauseMBMSNoMulticastServiceForThisUE\n\tRANAPCauseMBMSUnknownUEID\n\tRANAPCauseSuccessfulMBMSSessionStartNoDataBearerNecessary\n\tRANAPCauseMBMSSupersededDueToNNSF\n\tRANAPCauseMBMSUELinkingAlreadyDone\n\tRANAPCauseMBMSUEDeLinkingFailureNoExistingUELinking\n\tRANAPCauseTMGIUnknown\n\tRANAPCauseSignallingTransportResourceFailure\n\tRANAPCauseIuTransportConnectionFailedToEstablish\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tRANAPCauseUserRestrictionStartIndication\n\tRANAPCauseUserRestrictionEndIndication\n\tRANAPCauseNormalRelease\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tRANAPCauseTransferSyntaxError\n\tRANAPCauseSemanticError\n\tRANAPCauseMessageNotCompatibleWithReceiverState\n\tRANAPCauseAbstractSyntaxErrorReject\n\tRANAPCauseAbstractSyntaxErrorIgnoreAndNotify\n\tRANAPCauseAbstractSyntaxErrorFalselyConstructedMessage\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tRANAPCauseOAMIntervention\n\tRANAPCauseNoResourceAvailable\n\tRANAPCauseUnspecifiedFailure\n\tRANAPCauseNetworkOptimisation\n)\n"
  },
  {
    "path": "gtpv1/doc.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package gtpv1 provides simple and painless handling of GTPv1-C and GTPv1-U protocol in pure Golang.\n//\n// Please see README.md for detailed usage of the APIs provided by this package.\n//\n// https://github.com/wmnsk/go-gtp/blob/main/gtpv1/README.md\npackage gtpv1\n"
  },
  {
    "path": "gtpv1/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar (\n\t// ErrUnexpectedType indicates that the type of incoming message is not expected.\n\tErrUnexpectedType = errors.New(\"got unexpected type of message\")\n\n\t// ErrInvalidConnection indicates that the connection type(C-Plane or U-Plane) is\n\t// not the expected one.\n\tErrInvalidConnection = errors.New(\"got invalid connection type\")\n\n\t// ErrConnNotOpened indicates that some operation is failed due to the status of\n\t// Conn is not valid.\n\tErrConnNotOpened = errors.New(\"connection is not opened\")\n)\n\n// ErrorIndicatedError indicates that Error Indication message is received on U-Plane Connection.\ntype ErrorIndicatedError struct {\n\tTEID uint32\n\tPeer string\n}\n\nfunc (e *ErrorIndicatedError) Error() string {\n\treturn fmt.Sprintf(\"error received from %s, TEIDDataI: %#x\", e.Peer, e.TEID)\n}\n\n// HandlerNotFoundError indicates that the handler func is not registered in *Conn\n// for the incoming GTPv2 message. In usual cases this error should not be taken\n// as fatal, as the other endpoint can make your program stop working just by\n// sending unregistered message.\ntype HandlerNotFoundError struct {\n\tMsgType string\n}\n\n// Error returns violating message type to handle.\nfunc (e *HandlerNotFoundError) Error() string {\n\treturn fmt.Sprintf(\"no handlers found for incoming message: %s, ignoring\", e.MsgType)\n}\n"
  },
  {
    "path": "gtpv1/gtpv1_fuzz_test.go",
    "content": "package gtpv1_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n)\n\nfunc FuzzDecapsulate(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, _, err := gtpv1.Decapsulate(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv1/handlers.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n)\n\n// HandlerFunc is a handler for specific GTPv1 message.\ntype HandlerFunc func(c Conn, senderAddr net.Addr, msg message.Message) error\n\ntype msgHandlerMap struct {\n\tsyncMap sync.Map\n}\n\nfunc (m *msgHandlerMap) store(msgType uint8, handler HandlerFunc) {\n\tm.syncMap.Store(msgType, handler)\n}\n\nfunc (m *msgHandlerMap) load(msgType uint8) (HandlerFunc, bool) {\n\thandler, ok := m.syncMap.Load(msgType)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\n\treturn handler.(HandlerFunc), true\n}\n\nfunc newMsgHandlerMap(m map[uint8]HandlerFunc) *msgHandlerMap {\n\tmhm := &msgHandlerMap{syncMap: sync.Map{}}\n\tfor k, v := range m {\n\t\tmhm.store(k, v)\n\t}\n\n\treturn mhm\n}\n\nfunc newDefaultMsgHandlerMap() *msgHandlerMap {\n\treturn newMsgHandlerMap(\n\t\tmap[uint8]HandlerFunc{\n\t\t\tmessage.MsgTypeTPDU:            handleTPDU,\n\t\t\tmessage.MsgTypeEchoRequest:     handleEchoRequest,\n\t\t\tmessage.MsgTypeEchoResponse:    handleEchoResponse,\n\t\t\tmessage.MsgTypeErrorIndication: handleErrorIndication,\n\t\t},\n\t)\n}\n\n// handleTPDU responds to sender with ErrorIndication by default.\n// By disabling it(DisableErrorIndication), it passes unhandled T-PDU to\n// user, which can be caught by calling ReadFromGTP.\nfunc handleTPDU(c Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tpdu, ok := msg.(*message.TPDU)\n\tif !ok {\n\t\treturn ErrUnexpectedType\n\t}\n\n\tu, ok := c.(*UPlaneConn)\n\tif !ok {\n\t\treturn ErrInvalidConnection\n\t}\n\n\tif u.errIndEnabled {\n\t\tif err := u.ErrorIndication(senderAddr, pdu); err != nil {\n\t\t\tlogf(\"failed to send Error Indication to %s: %v\", senderAddr, err)\n\t\t}\n\t\treturn nil\n\t}\n\n\ttpdu := &tpduSet{\n\t\traddr:   senderAddr,\n\t\tteid:    pdu.TEID(),\n\t\tseq:     pdu.Sequence(),\n\t\tpayload: pdu.Payload,\n\t}\n\n\t// wait for the T-PDU passed to u.tpduCh to be read by ReadFromGTP.\n\t// if it got stuck for 3 seconds, it discards the T-PDU received.\n\tgo func() {\n\t\tselect {\n\t\tcase u.tpduCh <- tpdu:\n\t\t\treturn\n\t\tcase <-time.After(3 * time.Second):\n\t\t\treturn\n\t\t}\n\t}()\n\treturn nil\n}\n\nfunc handleEchoRequest(c Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tif _, ok := msg.(*message.EchoRequest); !ok {\n\t\treturn ErrUnexpectedType\n\t}\n\n\t// respond with EchoResponse.\n\treturn c.RespondTo(\n\t\tsenderAddr, msg, message.NewEchoResponse(0, ie.NewRecovery(c.Restarts())),\n\t)\n}\n\nfunc handleEchoResponse(c Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tif _, ok := msg.(*message.EchoResponse); !ok {\n\t\treturn ErrUnexpectedType\n\t}\n\n\t// do nothing.\n\treturn nil\n}\n\nfunc handleErrorIndication(c Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tind, ok := msg.(*message.ErrorIndication)\n\tif !ok {\n\t\treturn ErrUnexpectedType\n\t}\n\n\t// just log and return\n\tlogf(\"Ignored Error Indication: %v\", &ErrorIndicatedError{\n\t\tTEID: ind.TEIDDataI.MustTEID(),\n\t\tPeer: ind.GTPUPeerAddress.MustIPAddress(),\n\t})\n\treturn nil\n}\n"
  },
  {
    "path": "gtpv1/ie/apn-restriction.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewAPNRestriction creates a new APNRestriction IE.\nfunc NewAPNRestriction(restriction uint8) *IE {\n\treturn newUint8ValIE(APNRestriction, restriction)\n}\n\n// APNRestriction returns APNRestriction in uint8 if type matches.\nfunc (i *IE) APNRestriction() (uint8, error) {\n\tif i.Type != APNRestriction {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustAPNRestriction returns APNRestriction in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAPNRestriction() uint8 {\n\tv, _ := i.APNRestriction()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/apn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"strings\"\n)\n\n// NewAccessPointName creates a new AccessPointName IE.\nfunc NewAccessPointName(apn string) *IE {\n\ti := New(AccessPointName, make([]byte, len(apn)+1))\n\tvar offset = 0\n\tfor _, label := range strings.Split(apn, \".\") {\n\t\tl := len(label)\n\t\ti.Payload[offset] = uint8(l)\n\t\tcopy(i.Payload[offset+1:], label)\n\t\toffset += l + 1\n\t}\n\n\treturn i\n}\n\n// AccessPointName returns AccessPointName in string if type of IE matches.\nfunc (i *IE) AccessPointName() (string, error) {\n\tif i.Type != AccessPointName {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\n\tvar (\n\t\tapn    []string\n\t\toffset int\n\t)\n\n\tmax := len(i.Payload)\n\tfor {\n\t\tif offset >= max {\n\t\t\tbreak\n\t\t}\n\t\tl := int(i.Payload[offset])\n\t\tif offset+l+1 > max {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\tapn = append(apn, string(i.Payload[offset+1:offset+l+1]))\n\t\toffset += l + 1\n\t}\n\n\treturn strings.Join(apn, \".\"), nil\n}\n\n// MustAccessPointName returns AccessPointName in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAccessPointName() string {\n\tv, _ := i.AccessPointName()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/authentication-quintuplet.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewAuthenticationQuintuplet creates a new AuthenticationQuintuplet IE.\nfunc NewAuthenticationQuintuplet(rand, xres, ck, ik, autn []byte) *IE {\n\txresLen := len(xres)\n\tautnLen := len(autn)\n\ti := New(AuthenticationQuintuplet, make([]byte, 16+1+xresLen+16+16+1+autnLen))\n\n\tcopy(i.Payload[0:16], rand)\n\ti.Payload[16] = uint8(xresLen)\n\toffset := 17 // variable length appears from here.\n\tcopy(i.Payload[offset:offset+xresLen], xres)\n\toffset += xresLen\n\tcopy(i.Payload[offset:offset+16], ck)\n\toffset += 16\n\tcopy(i.Payload[offset:offset+16], ik)\n\toffset += 16\n\ti.Payload[offset] = uint8(autnLen)\n\toffset++\n\tcopy(i.Payload[offset:offset+autnLen], autn)\n\n\treturn i\n}\n\n// AuthenticationQuintuplet returns AuthenticationQuintuplet in []byte if type matches.\nfunc (i *IE) AuthenticationQuintuplet() ([]byte, error) {\n\tif i.Type != AuthenticationQuintuplet {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload, nil\n}\n\n// MustAuthenticationQuintuplet returns AuthenticationQuintuplet in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAuthenticationQuintuplet() []byte {\n\tv, _ := i.AuthenticationQuintuplet()\n\treturn v\n}\n\n// XRES returns XRES in []byte if type matches.\nfunc (i *IE) XRES() ([]byte, error) {\n\tif len(i.Payload) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tswitch i.Type {\n\tcase AuthenticationQuintuplet:\n\t\tif len(i.Payload) < 17 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\n\t\txresLen := i.Payload[16]\n\t\tif len(i.Payload) < 17+int(xresLen) {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[17 : 17+int(xresLen)], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustXRES returns XRES in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustXRES() []byte {\n\tv, _ := i.XRES()\n\treturn v\n}\n\n// CK returns CK in []byte if type matches.\nfunc (i *IE) CK() ([]byte, error) {\n\tswitch i.Type {\n\tcase AuthenticationQuintuplet:\n\t\tif len(i.Payload) < 18 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\n\t\toffset := 17 + int(i.Payload[16])\n\t\tif len(i.Payload) < offset+16 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[offset : offset+16], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCK returns CK in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCK() []byte {\n\tv, _ := i.CK()\n\treturn v\n}\n\n// IK returns IK in []byte if type matches.\nfunc (i *IE) IK() ([]byte, error) {\n\tswitch i.Type {\n\tcase AuthenticationQuintuplet:\n\t\tif len(i.Payload) < 34 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\n\t\toffset := 33 + int(i.Payload[16])\n\t\tif len(i.Payload) < offset+16 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[offset : offset+16], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustIK returns IK in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIK() []byte {\n\tv, _ := i.IK()\n\treturn v\n}\n\n// AUTN returns AUTN in []byte if type matches.\nfunc (i *IE) AUTN() ([]byte, error) {\n\tswitch i.Type {\n\tcase AuthenticationQuintuplet:\n\t\tif len(i.Payload) < 50 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\toffset := 49 + int(i.Payload[16])\n\t\tautnLen := i.Payload[50]\n\t\tif len(i.Payload) < offset+int(autnLen) {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[offset : offset+int(autnLen)], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustAUTN returns AUTN in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAUTN() []byte {\n\tv, _ := i.AUTN()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/authentication-triplet.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewAuthenticationTriplet creates a new AuthenticationTriplet IE.\nfunc NewAuthenticationTriplet(rand, sres, kc []byte) *IE {\n\ti := New(AuthenticationTriplet, make([]byte, 28))\n\n\tcopy(i.Payload[0:16], rand)\n\tcopy(i.Payload[16:20], sres)\n\tcopy(i.Payload[20:28], kc)\n\treturn i\n}\n\n// AuthenticationTriplet returns AuthenticationTriplet in []byte if type matches.\nfunc (i *IE) AuthenticationTriplet() ([]byte, error) {\n\tif i.Type != AuthenticationTriplet {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustAuthenticationTriplet returns AuthenticationTriplet in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAuthenticationTriplet() []byte {\n\tv, _ := i.AuthenticationTriplet()\n\treturn v\n}\n\n// RAND returns RAND in []byte if type matches.\nfunc (i *IE) RAND() ([]byte, error) {\n\tswitch i.Type {\n\tcase AuthenticationTriplet, AuthenticationQuintuplet:\n\t\tif len(i.Payload) < 16 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[0:16], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustRAND returns RAND in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRAND() []byte {\n\tv, _ := i.RAND()\n\treturn v\n}\n\n// SRES returns SRES in []byte if type matches.\nfunc (i *IE) SRES() ([]byte, error) {\n\tswitch i.Type {\n\tcase AuthenticationTriplet:\n\t\tif len(i.Payload) < 20 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[16:20], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustSRES returns SRES in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustSRES() []byte {\n\tv, _ := i.SRES()\n\treturn v\n}\n\n// Kc returns Kc in []byte if type matches.\nfunc (i *IE) Kc() ([]byte, error) {\n\tswitch i.Type {\n\tcase AuthenticationTriplet:\n\t\tif len(i.Payload) < 28 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[20:28], nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustKc returns Kc in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustKc() []byte {\n\tv, _ := i.Kc()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/cause.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewCause creates a new Cause IE.\nfunc NewCause(cause uint8) *IE {\n\treturn newUint8ValIE(Cause, cause)\n}\n\n// Cause returns the Cause value if type matches.\nfunc (i *IE) Cause() (uint8, error) {\n\tif i.Type != Cause {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustCause returns Cause in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCause() uint8 {\n\tv, _ := i.Cause()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/charging-id.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewChargingID creates a new ChargingID IE.\nfunc NewChargingID(id uint32) *IE {\n\treturn newUint32ValIE(ChargingID, id)\n}\n\n// ChargingID returns the ChargingID value in uint32 if the type of IE matches.\nfunc (i *IE) ChargingID() (uint32, error) {\n\tif i.Type != ChargingID {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload), nil\n}\n\n// MustChargingID returns ChargingID in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustChargingID() uint32 {\n\tv, _ := i.ChargingID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/common-flags.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewCommonFlags creates a new CommonFlags IE.\n//\n// Note: each flag should be set in 1 or 0.\nfunc NewCommonFlags(dualAddr, upgradeQoS, nrsn, noQoS, mbmsCount, ranReady, mbmsService, prohibitComp int) *IE {\n\treturn New(\n\t\tCommonFlags,\n\t\t[]byte{uint8(\n\t\t\tdualAddr<<7 | upgradeQoS<<6 | nrsn<<5 | noQoS<<4 | mbmsCount<<3 | ranReady<<2 | mbmsService<<1 | prohibitComp,\n\t\t)},\n\t)\n}\n\n// CommonFlags returns CommonFlags value if type matches.\nfunc (i *IE) CommonFlags() (uint8, error) {\n\tif i.Type != CommonFlags {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustCommonFlags returns CommonFlags in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCommonFlags() uint8 {\n\tv, _ := i.CommonFlags()\n\treturn v\n}\n\n// IsDualAddressBearer checks if DualAddressBearer flag exists in CommonFlags.\nfunc (i *IE) IsDualAddressBearer() bool {\n\treturn ((i.MustCommonFlags() >> 7) & 0x01) != 0\n}\n\n// IsUpgradeQoSSupported checks if UpgradeQoSSupported flag exists in CommonFlags.\nfunc (i *IE) IsUpgradeQoSSupported() bool {\n\treturn ((i.MustCommonFlags() >> 6) & 0x01) != 0\n}\n\n// IsNRSN checks if NRSN flag exists in CommonFlags.\nfunc (i *IE) IsNRSN() bool {\n\treturn ((i.MustCommonFlags() >> 5) & 0x01) != 0\n}\n\n// IsNoQoSNegotiation checks if NoQoSNegotiation flag exists in CommonFlags.\nfunc (i *IE) IsNoQoSNegotiation() bool {\n\treturn ((i.MustCommonFlags() >> 4) & 0x01) != 0\n}\n\n// IsMBMSCountingInformation checks if MBMSCountingInformation flag exists in CommonFlags.\nfunc (i *IE) IsMBMSCountingInformation() bool {\n\treturn ((i.MustCommonFlags() >> 3) & 0x01) != 0\n}\n\n// IsRANProceduresReady checks if RANProceduresReady flag exists in CommonFlags.\nfunc (i *IE) IsRANProceduresReady() bool {\n\treturn ((i.MustCommonFlags() >> 2) & 0x01) != 0\n}\n\n// IsMBMSServiceType checks if MBMSServiceType flag exists in CommonFlags.\nfunc (i *IE) IsMBMSServiceType() bool {\n\treturn ((i.MustCommonFlags() >> 1) & 0x01) != 0\n}\n\n// IsProhibitPayloadCompression checks if ProhibitPayloadCompression flag exists in CommonFlags.\nfunc (i *IE) IsProhibitPayloadCompression() bool {\n\treturn (i.MustCommonFlags() & 0x01) != 0\n}\n"
  },
  {
    "path": "gtpv1/ie/end-user-address.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\nconst (\n\tpdpTypeETSI uint8 = iota | 0xf0\n\tpdpTypeIETF\n)\n\n// NewEndUserAddress creates a new EndUserAddress IE from the given IP Address in string.\n//\n// The addr can be either IPv4 or IPv6. If the address type is PPP,\n// just put \"ppp\" in addr parameter or use NewEndUserAddressPPP func instead.\nfunc NewEndUserAddress(addr string) *IE {\n\tif addr == \"ppp\" {\n\t\treturn NewEndUserAddressPPP()\n\t}\n\n\treturn NewEndUserAddressByIP(net.ParseIP(addr))\n}\n\n// NewEndUserAddressByIP creates a new EndUserAddress IE from net.IP.\nfunc NewEndUserAddressByIP(ip net.IP) *IE {\n\tif ip == nil {\n\t\treturn nil\n\t}\n\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn newEUAddrV4(v4)\n\t}\n\n\treturn newEUAddrV6(ip)\n}\n\n// NewEndUserAddressIPv4 creates a new EndUserAddress IE with IPv4.\nfunc NewEndUserAddressIPv4(addr string) *IE {\n\tv4 := net.ParseIP(addr).To4()\n\tif v4 == nil {\n\t\treturn New(EndUserAddress, []byte{0xf1, 0x21})\n\t}\n\n\treturn newEUAddrV4(v4)\n}\n\n// NewEndUserAddressIPv6 creates a new EndUserAddress IE with IPv6.\nfunc NewEndUserAddressIPv6(addr string) *IE {\n\tv6 := net.ParseIP(addr).To16()\n\tif v6 == nil {\n\t\treturn New(EndUserAddress, []byte{0xf1, 0x57})\n\t}\n\n\treturn newEUAddrV6(v6)\n}\n\nfunc newEUAddrV4(v4 []byte) *IE {\n\te := New(\n\t\tEndUserAddress,\n\t\tmake([]byte, 6),\n\t)\n\te.Payload[0] = pdpTypeIETF\n\te.Payload[1] = 0x21\n\tcopy(e.Payload[2:], v4)\n\n\treturn e\n}\n\nfunc newEUAddrV6(v6 []byte) *IE {\n\te := New(\n\t\tEndUserAddress,\n\t\tmake([]byte, 18),\n\t)\n\te.Payload[0] = pdpTypeIETF\n\te.Payload[1] = 0x57\n\tcopy(e.Payload[2:], v6)\n\n\treturn e\n}\n\n// NewEndUserAddressPPP creates a new EndUserAddress IE with PPP.\nfunc NewEndUserAddressPPP() *IE {\n\te := New(EndUserAddress, make([]byte, 2))\n\te.Payload[0] = pdpTypeETSI\n\te.Payload[1] = pdpTypeIETF\n\n\te.SetLength()\n\treturn e\n}\n\n// EndUserAddress returns EndUserAddress value if type matches.\nfunc (i *IE) EndUserAddress() ([]byte, error) {\n\tif i.Type != EndUserAddress {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustEndUserAddress returns EndUserAddress in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustEndUserAddress() []byte {\n\tv, _ := i.EndUserAddress()\n\treturn v\n}\n\n// PDPTypeOrganization returns PDPTypeOrganization if type matches.\nfunc (i *IE) PDPTypeOrganization() (uint8, error) {\n\tif i.Type != EndUserAddress {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustPDPTypeOrganization returns PDPTypeOrganization in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPDPTypeOrganization() uint8 {\n\tv, _ := i.PDPTypeOrganization()\n\treturn v\n}\n\n// PDPTypeNumber returns PDPTypeNumber if type matches.\nfunc (i *IE) PDPTypeNumber() (uint8, error) {\n\tif i.Type != EndUserAddress {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[1], nil\n}\n\n// MustPDPTypeNumber returns PDPTypeNumber in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPDPTypeNumber() uint8 {\n\tv, _ := i.PDPTypeNumber()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Error definitions.\nvar (\n\tErrInvalidLength     = errors.New(\"got invalid length \")\n\tErrTooShortToMarshal = errors.New(\"too short to serialize\")\n\tErrTooShortToParse   = errors.New(\"too short to decode as GTPv1 IE\")\n\n\tErrMalformed = errors.New(\"malformed IE\")\n)\n\n// InvalidTypeError indicates the type of IE is invalid.\ntype InvalidTypeError struct {\n\tType uint8\n}\n\n// Error returns message with the invalid type given.\nfunc (e *InvalidTypeError) Error() string {\n\treturn fmt.Sprintf(\"got invalid type: %v\", e.Type)\n}\n"
  },
  {
    "path": "gtpv1/ie/extended-common-flags-ii.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewExtendedCommonFlagsII creates a new ExtendedCommonFlagsII IE.\n//\n// Note: each flag should be set in 1 or 0.\nfunc NewExtendedCommonFlagsII(pmtsmi, dtci, pnsi int) *IE {\n\treturn New(\n\t\tExtendedCommonFlagsII,\n\t\t[]byte{uint8(\n\t\t\tpmtsmi<<2 | dtci<<1 | pnsi,\n\t\t)},\n\t)\n}\n\n// ExtendedCommonFlagsII returns ExtendedCommonFlagsII value if type matches.\nfunc (i *IE) ExtendedCommonFlagsII() (uint8, error) {\n\tif i.Type != ExtendedCommonFlagsII {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustExtendedCommonFlagsII returns ExtendedCommonFlagsII in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtendedCommonFlagsII() uint8 {\n\tv, _ := i.ExtendedCommonFlagsII()\n\treturn v\n}\n\n// IsPMTSMI checks if PMTSMI flag exists in ExtendedCommonFlagsII.\nfunc (i *IE) IsPMTSMI() bool {\n\treturn ((i.MustExtendedCommonFlagsII() >> 2) & 0x01) != 0\n}\n\n// IsDTCI checks if DTCI flag exists in ExtendedCommonFlagsII.\nfunc (i *IE) IsDTCI() bool {\n\treturn ((i.MustExtendedCommonFlagsII() >> 1) & 0x01) != 0\n}\n\n// IsPNSI checks if PNSI flag exists in ExtendedCommonFlagsII.\nfunc (i *IE) IsPNSI() bool {\n\treturn (i.MustExtendedCommonFlagsII() & 0x01) != 0\n}\n"
  },
  {
    "path": "gtpv1/ie/extended-common-flags.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewExtendedCommonFlags creates a new ExtendedCommonFlags IE.\n//\n// Note: each flag should be set in 1 or 0.\nfunc NewExtendedCommonFlags(uasi, bdwi, pcri, vb, retloc, cpsr, ccrsi, unauthenticatedIMSI int) *IE {\n\treturn New(\n\t\tExtendedCommonFlags,\n\t\t[]byte{uint8(\n\t\t\tuasi<<7 | bdwi<<6 | pcri<<5 | vb<<4 | retloc<<3 | cpsr<<2 | ccrsi<<1 | unauthenticatedIMSI,\n\t\t)},\n\t)\n}\n\n// ExtendedCommonFlags returns ExtendedCommonFlags value if type matches.\nfunc (i *IE) ExtendedCommonFlags() (uint8, error) {\n\tif i.Type != ExtendedCommonFlags {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustExtendedCommonFlags returns ExtendedCommonFlags in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtendedCommonFlags() uint8 {\n\tv, _ := i.ExtendedCommonFlags()\n\treturn v\n}\n\n// IsUASI checks if UASI flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsUASI() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 7) & 0x01) != 0\n}\n\n// IsBDWI checks if BDWI flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsBDWI() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 6) & 0x01) != 0\n}\n\n// IsPCRI checks if PCRI flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsPCRI() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 5) & 0x01) != 0\n}\n\n// IsVB checks if VB flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsVB() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 4) & 0x01) != 0\n}\n\n// IsRetLoc checks if RetLoc flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsRetLoc() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 3) & 0x01) != 0\n}\n\n// IsCPSR checks if CPSR flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsCPSR() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 2) & 0x01) != 0\n}\n\n// IsCCRSI checks if CCRSI flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsCCRSI() bool {\n\treturn ((i.MustExtendedCommonFlags() >> 1) & 0x01) != 0\n}\n\n// IsUnauthenticatedIMSI checks if UnauthenticatedIMSI flag exists in ExtendedCommonFlags.\nfunc (i *IE) IsUnauthenticatedIMSI() bool {\n\treturn (i.MustExtendedCommonFlags() & 0x01) != 0\n}\n"
  },
  {
    "path": "gtpv1/ie/extension-header-type-list.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewExtensionHeaderTypeList creates a new ExtensionHeaderTypeList IE.\nfunc NewExtensionHeaderTypeList(types ...uint8) *IE {\n\treturn New(ExtensionHeaderTypeList, types)\n}\n\n// ExtensionHeaderTypeList returns ExtensionHeaderTypeList in []uint8 if type matches.\nfunc (i *IE) ExtensionHeaderTypeList() ([]uint8, error) {\n\tif i.Type != ExtensionHeaderTypeList {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\n\treturn i.Payload, nil\n}\n\n// MustExtensionHeaderTypeList returns ExtensionHeaderTypeList in []uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtensionHeaderTypeList() []uint8 {\n\tv, _ := i.ExtensionHeaderTypeList()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/gsn-address.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// NewGSNAddress creates a new GSNAddress IE.\nfunc NewGSNAddress(addr string) *IE {\n\treturn NewGSNAddressByIP(net.ParseIP(addr))\n}\n\n// NewGSNAddressByIP creates a new GSNAddress IE from net.IP.\nfunc NewGSNAddressByIP(ip net.IP) *IE {\n\tif ip == nil {\n\t\treturn nil\n\t}\n\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn New(GSNAddress, v4)\n\t}\n\t// IPv6\n\treturn New(GSNAddress, ip)\n}\n\n// GSNAddress returns GSNAddress value if type matches.\nfunc (i *IE) GSNAddress() (string, error) {\n\tif i.Type != GSNAddress {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn net.IP(i.Payload).String(), nil\n}\n\n// MustGSNAddress returns GSNAddress in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustGSNAddress() string {\n\tv, _ := i.GSNAddress()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/ie.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n/*\nPackage ie provides encoding/decoding feature of GTPv1 Information Elements.\n*/\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n)\n\n// TV IE definitions.\nconst (\n\tCause                        uint8 = 1\n\tIMSI                         uint8 = 2\n\tRouteingAreaIdentity         uint8 = 3\n\tTemporaryLogicalLinkIdentity uint8 = 4\n\tPacketTMSI                   uint8 = 5\n\tReorderingRequired           uint8 = 8\n\tAuthenticationTriplet        uint8 = 9\n\tMAPCause                     uint8 = 11\n\tPTMSISignature               uint8 = 12\n\tMSValidated                  uint8 = 13\n\tRecovery                     uint8 = 14\n\tSelectionMode                uint8 = 15\n\tTEIDDataI                    uint8 = 16\n\tTEIDCPlane                   uint8 = 17\n\tTEIDDataII                   uint8 = 18\n\tTeardownInd                  uint8 = 19\n\tNSAPI                        uint8 = 20\n\tRANAPCause                   uint8 = 21\n\tRABContext                   uint8 = 22\n\tRadioPrioritySMS             uint8 = 23\n\tRadioPriority                uint8 = 24\n\tPacketFlowID                 uint8 = 25\n\tChargingCharacteristics      uint8 = 26\n\tTraceReference               uint8 = 27\n\tTraceType                    uint8 = 28\n\tMSNotReachableReason         uint8 = 29\n\tChargingID                   uint8 = 127\n)\n\n// TLV IE definitions.\nconst (\n\tEndUserAddress                        uint8 = 128\n\tMMContext                             uint8 = 129\n\tPDPContext                            uint8 = 130\n\tAccessPointName                       uint8 = 131\n\tProtocolConfigurationOptions          uint8 = 132\n\tGSNAddress                            uint8 = 133\n\tMSISDN                                uint8 = 134\n\tQoSProfile                            uint8 = 135\n\tAuthenticationQuintuplet              uint8 = 136\n\tTrafficFlowTemplate                   uint8 = 137\n\tTargetIdentification                  uint8 = 138\n\tUTRANTransparentContainer             uint8 = 139\n\tRABSetupInformation                   uint8 = 140\n\tExtensionHeaderTypeList               uint8 = 141\n\tTriggerID                             uint8 = 142\n\tOMCIdentity                           uint8 = 143\n\tRANTransparentContainer               uint8 = 144\n\tPDPContextPrioritization              uint8 = 145\n\tAdditionalRABSetupInformation         uint8 = 146\n\tSGSNNumber                            uint8 = 147\n\tCommonFlags                           uint8 = 148\n\tAPNRestriction                        uint8 = 149\n\tRadioPriorityLCS                      uint8 = 150\n\tRATType                               uint8 = 151\n\tUserLocationInformation               uint8 = 152\n\tMSTimeZone                            uint8 = 153\n\tIMEISV                                uint8 = 154\n\tCAMELChargingInformationContainer     uint8 = 155\n\tMBMSUEContext                         uint8 = 156\n\tTemporaryMobileGroupIdentity          uint8 = 157\n\tRIMRoutingAddress                     uint8 = 158\n\tMBMSProtocolConfigurationOptions      uint8 = 159\n\tMBMSServiceArea                       uint8 = 160\n\tSourceRNCPDCPContextInfo              uint8 = 161\n\tAdditionalTraceInfo                   uint8 = 162\n\tHopCounter                            uint8 = 163\n\tSelectedPLMNID                        uint8 = 164\n\tMBMSSessionIdentifier                 uint8 = 165\n\tMBMS2G3GIndicator                     uint8 = 166\n\tEnhancedNSAPI                         uint8 = 167\n\tMBMSSessionDuration                   uint8 = 168\n\tAdditionalMBMSTraceInfo               uint8 = 169\n\tMBMSSessionRepetitionNumber           uint8 = 170\n\tMBMSTimeToDataTransfer                uint8 = 171\n\tBSSContainer                          uint8 = 173\n\tCellIdentification                    uint8 = 174\n\tPDUNumbers                            uint8 = 175\n\tBSSGPCause                            uint8 = 176\n\tRequiredMBMSBearerCapabilities        uint8 = 177\n\tRIMRoutingAddressDiscriminator        uint8 = 178\n\tListOfSetupPFCs                       uint8 = 179\n\tPSHandoverXIDParameters               uint8 = 180\n\tMSInfoChangeReportingAction           uint8 = 181\n\tDirectTunnelFlags                     uint8 = 182\n\tCorrelationID                         uint8 = 183\n\tBearerControlMode                     uint8 = 184\n\tMBMSFlowIdentifier                    uint8 = 185\n\tMBMSIPMulticastDistribution           uint8 = 186\n\tMBMSDistributionAcknowledgement       uint8 = 187\n\tReliableInterRATHandoverInfo          uint8 = 188\n\tRFSPIndex                             uint8 = 189\n\tFullyQualifiedDomainName              uint8 = 190\n\tEvolvedAllocationRetentionPriorityI   uint8 = 191\n\tEvolvedAllocationRetentionPriorityII  uint8 = 192\n\tExtendedCommonFlags                   uint8 = 193\n\tUserCSGInformation                    uint8 = 194\n\tCSGInformationReportingAction         uint8 = 195\n\tCSGID                                 uint8 = 196\n\tCSGMembershipIndication               uint8 = 197\n\tAggregateMaximumBitRate               uint8 = 198\n\tUENetworkCapability                   uint8 = 199\n\tUEAMBR                                uint8 = 200\n\tAPNAMBRWithNSAPI                      uint8 = 201\n\tGGSNBackOffTime                       uint8 = 202\n\tSignallingPriorityIndication          uint8 = 203\n\tSignallingPriorityIndicationWithNSAPI uint8 = 204\n\tHigherBitratesThan16MbpsFlag          uint8 = 205\n\tAdditionalMMContextForSRVCC           uint8 = 207\n\tAdditionalFlagsForSRVCC               uint8 = 208\n\tSTNSR                                 uint8 = 209\n\tCMSISDN                               uint8 = 210\n\tExtendedRANAPCause                    uint8 = 211\n\tENodeBID                              uint8 = 212\n\tSelectionModeWithNSAPI                uint8 = 213\n\tULITimestamp                          uint8 = 214\n\tLHNIDWithNSAPI                        uint8 = 215\n\tCNOperatorSelectionEntity             uint8 = 216\n\tUEUsageType                           uint8 = 217\n\tExtendedCommonFlagsII                 uint8 = 218\n\tNodeIdentifier                        uint8 = 219\n\tCIoTOptimizationsSupportIndication    uint8 = 220\n\tSCEFPDNConnection                     uint8 = 221\n\tIOVUpdatesCounter                     uint8 = 222\n\tMappedUEUsageType                     uint8 = 223\n\tUPFunctionSelectionIndicationFlags    uint8 = 224\n\tSpecialIETypeForIETypeExtension       uint8 = 238\n\tChargingGatewayAddress                uint8 = 251\n\tPrivateExtension                      uint8 = 255\n)\n\n// IE is a GTPv1 Information Element.\ntype IE struct {\n\tType    uint8\n\tLength  uint16\n\tPayload []byte\n}\n\n// New creates new IE.\nfunc New(t uint8, p []byte) *IE {\n\ti := &IE{Type: t, Payload: p}\n\ti.SetLength()\n\n\treturn i\n}\n\n// Marshal returns the byte sequence generated from an IE instance.\nfunc (i *IE) Marshal() ([]byte, error) {\n\tb := make([]byte, i.MarshalLen())\n\tif err := i.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (i *IE) MarshalTo(b []byte) error {\n\tif len(b) < i.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tvar offset = 1\n\tb[0] = i.Type\n\n\tif i.Type == ExtensionHeaderTypeList {\n\t\tb[1] = uint8(i.Length)\n\t\toffset++\n\t} else if !i.IsTV() {\n\t\tbinary.BigEndian.PutUint16(b[1:3], i.Length)\n\t\toffset += 2\n\t}\n\tcopy(b[offset:i.MarshalLen()], i.Payload)\n\treturn nil\n}\n\n// Parse decodes given byte sequence as a GTPv1 Information Element.\nfunc Parse(b []byte) (*IE, error) {\n\ti := &IE{}\n\tif err := i.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn i, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in GTPv1 IE.\nfunc (i *IE) UnmarshalBinary(b []byte) error {\n\tif len(b) < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\ti.Type = b[0]\n\tif i.Type == ExtensionHeaderTypeList {\n\t\treturn decodeExtensionHeaderTypeList(i, b)\n\t}\n\n\tif i.IsTV() {\n\t\treturn decodeTVFromBytes(i, b)\n\t}\n\n\treturn decodeTLVFromBytes(i, b)\n}\n\nfunc decodeTVFromBytes(i *IE, b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\tif i.MarshalLen() > l {\n\t\treturn ErrInvalidLength\n\t}\n\n\ti.Length = 0\n\ti.Payload = b[1:i.MarshalLen()]\n\n\treturn nil\n}\n\nfunc decodeTLVFromBytes(i *IE, b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\ti.Length = binary.BigEndian.Uint16(b[1:3])\n\tif int(i.Length)+3 > l {\n\t\treturn ErrInvalidLength\n\t}\n\n\ti.Payload = b[3 : 3+int(i.Length)]\n\treturn nil\n}\n\nfunc decodeExtensionHeaderTypeList(i *IE, b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\tif i.MarshalLen() > l {\n\t\treturn ErrInvalidLength\n\t}\n\n\ti.Length = uint16(b[1])\n\tn := 2 + int(i.Length)\n\tif n > l {\n\t\treturn ErrInvalidLength\n\t}\n\n\ti.Payload = b[2:n]\n\n\treturn nil\n}\n\nvar tvLengthMap = map[int]int{\n\t0:   0,  // Reserved\n\t1:   1,  // Cause\n\t2:   8,  // IMSI\n\t3:   6,  // RouteingAreaIdentity\n\t4:   4,  // TLLI\n\t5:   4,  // P-TMSI\n\t8:   1,  // Reorder Required\n\t9:   28, // Authentication Triplet\n\t11:  1,  // MAP Cause\n\t12:  3,  // P-TMSI Signature\n\t13:  1,  // MS Validated\n\t14:  1,  // Recovery\n\t15:  1,  // Selection Mode\n\t16:  4,  // TEID Data 1\n\t17:  4,  // TEID C-Plane\n\t18:  4,  // TEID Data 2\n\t19:  1,  // Teardown Indication\n\t20:  1,  // NSAPI\n\t21:  1,  // RANAP Cause\n\t22:  9,  // RAB Context\n\t23:  1,  // Radio Priority SMS\n\t24:  1,  // Radio Priority\n\t25:  2,  // Packet Flow ID\n\t26:  2,  // Charging Characteristics\n\t27:  2,  // Trace Preference\n\t28:  2,  // Trace Type\n\t29:  1,  // MS Not Reachable Reason\n\t127: 4,  // Charging ID\n}\n\n// IsTV checks if a IE is TV format. If false, it indicates the IE has Length inside.\nfunc (i *IE) IsTV() bool {\n\treturn int(i.Type) < 0x80\n}\n\n// MarshalLen returns the serial length of IE.\nfunc (i *IE) MarshalLen() int {\n\tif l, ok := tvLengthMap[int(i.Type)]; ok {\n\t\treturn l + 1\n\t}\n\n\tif i.Type < 128 {\n\t\treturn 1 + len(i.Payload)\n\t}\n\n\tif i.Type == ExtensionHeaderTypeList {\n\t\treturn 2 + len(i.Payload)\n\t}\n\n\treturn 3 + len(i.Payload)\n}\n\n// SetLength sets the length in Length field.\nfunc (i *IE) SetLength() {\n\tif _, ok := tvLengthMap[int(i.Type)]; ok {\n\t\ti.Length = 0\n\t\treturn\n\t}\n\n\ti.Length = uint16(len(i.Payload))\n}\n\n// Name returns the name of IE in string.\nfunc (i *IE) Name() string {\n\tif n, ok := ieTypeNameMap[i.Type]; ok {\n\t\treturn n\n\t}\n\treturn \"Undefined\"\n}\n\n// String returns the GTPv1 IE values in human readable format.\nfunc (i *IE) String() string {\n\tif i == nil {\n\t\treturn \"nil\"\n\t}\n\treturn fmt.Sprintf(\"{%s: {Type: %d, Length: %d, Payload: %#v}}\",\n\t\ti.Name(),\n\t\ti.Type,\n\t\ti.Length,\n\t\ti.Payload,\n\t)\n}\n\n// ParseMultiIEs decodes multiple (unspecified number of) IEs to []*IE at a time.\nfunc ParseMultiIEs(b []byte) ([]*IE, error) {\n\tvar ies []*IE\n\tfor {\n\t\tif len(b) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\ti, err := Parse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\ties = append(ies, i)\n\t\tb = b[i.MarshalLen():]\n\t\tcontinue\n\t}\n\treturn ies, nil\n}\n\nfunc newUint8ValIE(t, v uint8) *IE {\n\treturn New(t, []byte{v})\n}\n\n// left for future use.\n// func newUint16ValIE(t uint8, v uint16) *IE {\n// \ti := New(t, make([]byte, 2))\n// \tbinary.BigEndian.PutUint16(i.Payload, v)\n// \treturn i\n// }\n\nfunc newUint32ValIE(t uint8, v uint32) *IE {\n\ti := New(t, make([]byte, 4))\n\tbinary.BigEndian.PutUint32(i.Payload, v)\n\treturn i\n}\n\nvar ieTypeNameMap = map[uint8]string{\n\t128: \"EndUserAddress\",\n\t129: \"MMContext\",\n\t130: \"PDPContext\",\n\t131: \"AccessPointName\",\n\t132: \"ProtocolConfigurationOptions\",\n\t133: \"GSNAddress\",\n\t134: \"MSISDN\",\n\t135: \"QoSProfile\",\n\t136: \"AuthenticationQuintuplet\",\n\t137: \"TrafficFlowTemplate\",\n\t138: \"TargetIdentification\",\n\t139: \"UTRANTransparentContainer\",\n\t140: \"RABSetupInformation\",\n\t141: \"ExtensionHeaderTypeList\",\n\t142: \"TriggerID\",\n\t143: \"OMCIdentity\",\n\t144: \"RANTransparentContainer\",\n\t145: \"PDPContextPrioritization\",\n\t146: \"AdditionalRABSetupInformation\",\n\t147: \"SGSNNumber\",\n\t148: \"CommonFlags\",\n\t149: \"APNRestriction\",\n\t150: \"RadioPriorityLCS\",\n\t151: \"RATType\",\n\t152: \"UserLocationInformation\",\n\t153: \"MSTimeZone\",\n\t154: \"IMEISV\",\n\t155: \"CAMELChargingInformationContainer\",\n\t156: \"MBMSUEContext\",\n\t157: \"TemporaryMobileGroupIdentity\",\n\t158: \"RIMRoutingAddress\",\n\t159: \"MBMSProtocolConfigurationOptions\",\n\t160: \"MBMSServiceArea\",\n\t161: \"SourceRNCPDCPContextInfo\",\n\t162: \"AdditionalTraceInfo\",\n\t163: \"HopCounter\",\n\t164: \"SelectedPLMNID\",\n\t165: \"MBMSSessionIdentifier\",\n\t166: \"MBMS2G3GIndicator\",\n\t167: \"EnhancedNSAPI\",\n\t168: \"MBMSSessionDuration\",\n\t169: \"AdditionalMBMSTraceInfo\",\n\t170: \"MBMSSessionRepetitionNumber\",\n\t171: \"MBMSTimeToDataTransfer\",\n\t173: \"BSSContainer\",\n\t174: \"CellIdentification\",\n\t175: \"PDUNumbers\",\n\t176: \"BSSGPCause\",\n\t177: \"RequiredMBMSBearerCapabilities\",\n\t178: \"RIMRoutingAddressDiscriminator\",\n\t179: \"ListOfSetupPFCs\",\n\t180: \"PSHandoverXIDParameters\",\n\t181: \"MSInfoChangeReportingAction\",\n\t182: \"DirectTunnelFlags\",\n\t183: \"CorrelationID\",\n\t184: \"BearerControlMode\",\n\t185: \"MBMSFlowIdentifier\",\n\t186: \"MBMSIPMulticastDistribution\",\n\t187: \"MBMSDistributionAcknowledgement\",\n\t188: \"ReliableInterRATHandoverInfo\",\n\t189: \"RFSPIndex\",\n\t190: \"FullyQualifiedDomainName\",\n\t191: \"EvolvedAllocationRetentionPriorityI\",\n\t192: \"EvolvedAllocationRetentionPriorityII\",\n\t193: \"ExtendedCommonFlags\",\n\t194: \"UserCSGInformation\",\n\t195: \"CSGInformationReportingAction\",\n\t196: \"CSGID\",\n\t197: \"CSGMembershipIndication\",\n\t198: \"AggregateMaximumBitRate\",\n\t199: \"UENetworkCapability\",\n\t200: \"UEAMBR\",\n\t201: \"APNAMBRWithNSAPI\",\n\t202: \"GGSNBackOffTime\",\n\t203: \"SignallingPriorityIndication\",\n\t204: \"SignallingPriorityIndicationWithNSAPI\",\n\t205: \"HigherBitratesThan16MbpsFlag\",\n\t207: \"AdditionalMMContextForSRVCC\",\n\t208: \"AdditionalFlagsForSRVCC\",\n\t209: \"STNSR\",\n\t210: \"CMSISDN\",\n\t211: \"ExtendedRANAPCause\",\n\t212: \"ENodeBID\",\n\t213: \"SelectionModeWithNSAPI\",\n\t214: \"ULITimestamp\",\n\t215: \"LHNIDWithNSAPI\",\n\t216: \"CNOperatorSelectionEntity\",\n\t217: \"UEUsageType\",\n\t218: \"ExtendedCommonFlagsII\",\n\t219: \"NodeIdentifier\",\n\t220: \"CIoTOptimizationsSupportIndication\",\n\t221: \"SCEFPDNConnection\",\n\t222: \"IOVUpdatesCounter\",\n\t223: \"MappedUEUsageType\",\n\t224: \"UPFunctionSelectionIndicationFlags\",\n\t238: \"SpecialIETypeForIETypeExtension\",\n\t251: \"ChargingGatewayAddress\",\n\t255: \"PrivateExtension\",\n}\n"
  },
  {
    "path": "gtpv1/ie/ie_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"log\"\n\n// Serialize serializes IE into bytes.\n//\n// Deprecated: use IE.Marshal instead.\nfunc (i *IE) Serialize() ([]byte, error) {\n\tlog.Println(\"IE.Serialize is deprecated. use IE.Marshal instead\")\n\treturn i.Marshal()\n}\n\n// SerializeTo serializes IE into bytes given as b.\n//\n// Deprecated: use IE.MarshalTo instead.\nfunc (i *IE) SerializeTo(b []byte) error {\n\tlog.Println(\"IE.SerializeTo is deprecated. use IE.MarshalTo instead\")\n\treturn i.MarshalTo(b)\n}\n\n// Decode decodes bytes as IE.\n//\n// Deprecated: use Parse instead.\nfunc Decode(b []byte) (*IE, error) {\n\tlog.Println(\"Decode is deprecated. use Parse instead\")\n\treturn Parse(b)\n}\n\n// DecodeFromBytes decodes bytes as IE.\n//\n// Deprecated: use IE.UnmarshalBinary instead.\nfunc (i *IE) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"IE.DecodeFromBytes is deprecated. use IE.UnmarshalBinary instead\")\n\treturn i.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of IE.\n//\n// Deprecated: use IE.MarshalLen instead.\nfunc (i *IE) Len() int {\n\tlog.Println(\"IE.Len is deprecated. use IE.MarshalLen instead\")\n\treturn i.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/ie/ie_fuzz_test.go",
    "content": "package ie_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := ie.Parse(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv1/ie/ie_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n)\n\nfunc TestIEs(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  *ie.IE\n\t\tserialized  []byte\n\t}{\n\t\t{\n\t\t\t\"IMSI\",\n\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t[]byte{0x02, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0},\n\t\t}, {\n\t\t\t\"PacketTMSI\",\n\t\t\tie.NewPacketTMSI(0xbeebee),\n\t\t\t[]byte{0x05, 0x00, 0xbe, 0xeb, 0xee},\n\t\t}, {\n\t\t\t\"AuthenticationTriplet\",\n\t\t\tie.NewAuthenticationTriplet(\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},\n\t\t\t\t[]byte{0xde, 0xad, 0xbe, 0xef},\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77},\n\t\t\t),\n\t\t\t[]byte{\n\t\t\t\t0x09,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n\t\t\t},\n\t\t}, {\n\t\t\t\"MAPCause\",\n\t\t\tie.NewMAPCause(gtpv1.MAPCauseSystemFailure),\n\t\t\t[]byte{0x0b, 0x22},\n\t\t}, {\n\t\t\t\"PTMSISignature\",\n\t\t\tie.NewPTMSISignature(0xbeebee),\n\t\t\t[]byte{0x0c, 0xbe, 0xeb, 0xee},\n\t\t}, {\n\t\t\t\"MSValidated\",\n\t\t\tie.NewMSValidated(true),\n\t\t\t[]byte{0x0d, 0xff},\n\t\t}, {\n\t\t\t\"Recovery\",\n\t\t\tie.NewRecovery(1),\n\t\t\t[]byte{0x0e, 0x01},\n\t\t}, {\n\t\t\t\"SelectionMode\",\n\t\t\tie.NewSelectionMode(gtpv1.SelectionModeMSorNetworkProvidedAPNSubscribedVerified),\n\t\t\t[]byte{0x0f, 0xf0},\n\t\t}, {\n\t\t\t\"TEIDDataI\",\n\t\t\tie.NewTEIDDataI(0xdeadbeef),\n\t\t\t[]byte{0x10, 0xde, 0xad, 0xbe, 0xef},\n\t\t}, {\n\t\t\t\"TEIDCPlane\",\n\t\t\tie.NewTEIDCPlane(0xdeadbeef),\n\t\t\t[]byte{0x11, 0xde, 0xad, 0xbe, 0xef},\n\t\t}, {\n\t\t\t\"TEIDDataII\",\n\t\t\tie.NewTEIDDataII(0xdeadbeef),\n\t\t\t[]byte{0x12, 0xde, 0xad, 0xbe, 0xef},\n\t\t}, {\n\t\t\t\"TeardownInd\",\n\t\t\tie.NewTeardownInd(true),\n\t\t\t[]byte{0x13, 0xff},\n\t\t}, {\n\t\t\t\"NSAPI\",\n\t\t\tie.NewNSAPI(0x05),\n\t\t\t[]byte{0x14, 0x05},\n\t\t}, {\n\t\t\t\"RANAPCause\",\n\t\t\tie.NewRANAPCause(gtpv1.MAPCauseUnknownSubscriber),\n\t\t\t[]byte{0x15, 0x01},\n\t\t}, {\n\t\t\t\"EndUserAddress/v4\",\n\t\t\tie.NewEndUserAddress(\"1.1.1.1\"),\n\t\t\t[]byte{0x80, 0x00, 0x06, 0xf1, 0x21, 0x01, 0x01, 0x01, 0x01},\n\t\t}, {\n\t\t\t\"EndUserAddress/v6\",\n\t\t\tie.NewEndUserAddress(\"2001::1\"),\n\t\t\t[]byte{\n\t\t\t\t0x80, 0x00, 0x12, 0xf1,\n\t\t\t\t0x57, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"AccessPointName\",\n\t\t\tie.NewAccessPointName(\"some.apn.example\"),\n\t\t\t[]byte{\n\t\t\t\t0x83, 0x00, 0x11,\n\t\t\t\t0x04, 0x73, 0x6f, 0x6d, 0x65, 0x03, 0x61, 0x70, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,\n\t\t\t},\n\t\t}, {\n\t\t\t\"GSNAddressV4\",\n\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t[]byte{0x85, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01},\n\t\t}, {\n\t\t\t\"GSNAddressV6\",\n\t\t\tie.NewGSNAddress(\"2001::1\"),\n\t\t\t[]byte{\n\t\t\t\t0x85, 0x00, 0x10,\n\t\t\t\t0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t\t\t},\n\t\t}, {\n\t\t\t\"MSISDN\",\n\t\t\tie.NewMSISDN(\"818012345678\"),\n\t\t\t[]byte{0x86, 0x00, 0x07, 0x91, 0x18, 0x08, 0x21, 0x43, 0x65, 0x87},\n\t\t}, {\n\t\t\t\"AuthenticationQuintuplet\",\n\t\t\tie.NewAuthenticationQuintuplet(\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},\n\t\t\t\t[]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},\n\t\t\t),\n\t\t\t[]byte{\n\t\t\t\t0x88, 0x00, 0x52,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n\t\t\t\t0x10,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n\t\t\t\t0x10,\n\t\t\t\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n\t\t\t},\n\t\t}, {\n\t\t\t\"ExtensionHeaderTypeList\",\n\t\t\tie.NewExtensionHeaderTypeList(\n\t\t\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t),\n\t\t\t[]byte{0x8d, 0x02, 0x85, 0x40},\n\t\t}, {\n\t\t\t\"CommonFlags\",\n\t\t\tie.NewCommonFlags(0, 1, 0, 0, 0, 0, 0, 0),\n\t\t\t[]byte{0x94, 0x00, 0x01, 0x40},\n\t\t}, {\n\t\t\t\"APNRestriction\",\n\t\t\tie.NewAPNRestriction(gtpv1.APNRestrictionPrivate1),\n\t\t\t[]byte{0x95, 0x00, 0x01, 0x03},\n\t\t}, {\n\t\t\t\"RATType\",\n\t\t\tie.NewRATType(gtpv1.RatTypeEUTRAN),\n\t\t\t[]byte{0x97, 0x00, 0x01, 0x06},\n\t\t}, {\n\t\t\t\"UserLocationInformationWithCGI\",\n\t\t\tie.NewUserLocationInformationWithCGI(\"123\", \"45\", 0xff, 0),\n\t\t\t[]byte{0x98, 0x00, 0x08, 0x00, 0x21, 0xf3, 0x54, 0x00, 0xff, 0x00, 0x00},\n\t\t}, {\n\t\t\t\"UserLocationInformationWithSAI\",\n\t\t\tie.NewUserLocationInformationWithSAI(\"123\", \"45\", 0xff, 0),\n\t\t\t[]byte{0x98, 0x00, 0x08, 0x01, 0x21, 0xf3, 0x54, 0x00, 0xff, 0x00, 0x00},\n\t\t}, {\n\t\t\t\"UserLocationInformationWithRAI\",\n\t\t\tie.NewUserLocationInformationWithRAI(\"123\", \"45\", 0xff, 0),\n\t\t\t[]byte{0x98, 0x00, 0x07, 0x02, 0x21, 0xf3, 0x54, 0x00, 0xff, 0x00},\n\t\t}, {\n\t\t\t\"MSTimeZone\",\n\t\t\tie.NewMSTimeZone(9*time.Hour, 0), // XXX - should be updated with more realistic value\n\t\t\t[]byte{0x99, 0x00, 0x02, 0x63, 0x00},\n\t\t}, {\n\t\t\t\"MSTimeZone\",\n\t\t\tie.NewMSTimeZone(2*time.Hour, 0),\n\t\t\t[]byte{0x99, 0x00, 0x02, 0x80, 0x00},\n\t\t}, {\n\t\t\t\"IMEISV\",\n\t\t\tie.NewIMEISV(\"123450123456789\"),\n\t\t\t[]byte{0x9a, 0x00, 0x08, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9},\n\t\t}, {\n\t\t\t\"ULITimestamp\",\n\t\t\tie.NewULITimestamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),\n\t\t\t[]byte{0xd6, 0x00, 0x04, 0xdf, 0xd5, 0x2c, 0x00},\n\t\t}, {\n\t\t\t\"ChargingID\",\n\t\t\tie.NewChargingID(0xffffffff),\n\t\t\t[]byte{0x7f, 0xff, 0xff, 0xff, 0xff},\n\t\t},\n\t\t{\n\t\t\t\"PrivateExtension\",\n\t\t\tie.NewPrivateExtension(0x0080, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t[]byte{\n\t\t\t\t// Type, Length\n\t\t\t\t0xff, 0x00, 0x06,\n\t\t\t\t// Value\n\t\t\t\t0x00, 0x80, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"Marshal/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"Parse/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.Parse(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\topt := cmp.AllowUnexported(*got, *c.structured)\n\t\t\tif diff := cmp.Diff(got, c.structured, opt); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv1/ie/imei.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewIMEISV creates a new IMEISV IE.\nfunc NewIMEISV(imei string) *IE {\n\ti, err := utils.StrToSwappedBytes(imei, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn New(IMEISV, i)\n}\n\n// IMEISV returns IMEISV value if type matches.\nfunc (i *IE) IMEISV() (string, error) {\n\tif i.Type != IMEISV {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\tstr := utils.SwappedBytesToStr(i.Payload, false)\n\treturn strings.TrimSuffix(str, \"f\"), nil\n}\n\n// MustIMEISV returns IMEISV in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIMEISV() string {\n\tv, _ := i.IMEISV()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/imei_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"testing\"\n\nfunc TestIE_IMEISV(t *testing.T) {\n\tt.Run(\"Encode/Decode IMEI\", func(t *testing.T) {\n\t\tie := NewIMEISV(\"123456789012345\")\n\n\t\tgot := ie.MustIMEISV()\n\t\tif got != \"123456789012345\" {\n\t\t\tt.Errorf(\"wrong IMEI, got: %v\", got)\n\t\t}\n\t})\n\n\tt.Run(\"Encode/Decode IMEISV\", func(t *testing.T) {\n\t\tie := NewIMEISV(\"1234567890123456\")\n\n\t\tgot := ie.MustIMEISV()\n\t\tif got != \"1234567890123456\" {\n\t\t\tt.Errorf(\"wrong IMEISV, got: %v\", got)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv1/ie/imsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewIMSI creates a new IMSI IE.\nfunc NewIMSI(imsi string) *IE {\n\ti, err := utils.StrToSwappedBytes(imsi, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn New(IMSI, i)\n}\n\n// IMSI returns IMSI value if type matches.\nfunc (i *IE) IMSI() (string, error) {\n\tif i.Type != IMSI {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.SwappedBytesToStr(i.Payload, true), nil\n}\n\n// MustIMSI returns IMSI in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIMSI() string {\n\tv, _ := i.IMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/ip.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// IP returns IP in net.IP if type matches.\nfunc (i *IE) IP() (net.IP, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase EndUserAddress:\n\t\tif i.MustPDPTypeOrganization() != pdpTypeIETF {\n\t\t\treturn nil, ErrMalformed\n\t\t}\n\t\treturn net.IP(i.Payload[2:]), nil\n\tcase GSNAddress:\n\t\treturn net.IP(i.Payload), nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{i.Type}\n\t}\n}\n\nfunc (i *IE) MustIP() net.IP {\n\tv, _ := i.IP()\n\treturn v\n}\n\n// IPAddress returns IPAddress in string if type matches.\nfunc (i *IE) IPAddress() (string, error) {\n\tip, err := i.IP()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn ip.String(), nil\n}\n\n// MustIPAddress returns IPAddress in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIPAddress() string {\n\tv, _ := i.IPAddress()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/lac.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// LAC returns LAC value if type matches.\nfunc (i *IE) LAC() (uint16, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 5 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[3:5]), nil\n\tcase UserLocationInformation:\n\t\tif len(i.Payload) < 6 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[4:6]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustLAC returns LAC in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustLAC() uint16 {\n\tv, _ := i.LAC()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/map-cause.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewMAPCause creates a new MAPCause IE.\nfunc NewMAPCause(cause uint8) *IE {\n\treturn newUint8ValIE(MAPCause, cause)\n}\n\n// MAPCause returns MAPCause in uint8 if type matches.\nfunc (i *IE) MAPCause() (uint8, error) {\n\tif i.Type != MAPCause {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustMAPCause returns MAPCause in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMAPCause() uint8 {\n\tv, _ := i.MAPCause()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/mcc-mnc.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// MCC returns MCC value if type matches.\nfunc (i *IE) MCC() (string, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 2 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.DecodeMCC(i.Payload[0:2]), nil\n\tcase UserLocationInformation:\n\t\tif len(i.Payload) < 3 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.DecodeMCC(i.Payload[1:3]), nil\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMCC returns MCC in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMCC() string {\n\tv, _ := i.MCC()\n\treturn v\n}\n\n// MNC returns MNC value if type matches.\nfunc (i *IE) MNC() (string, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 3 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.DecodeMNC(i.Payload[1:3]), nil\n\tcase UserLocationInformation:\n\t\tif len(i.Payload) < 4 {\n\t\t\treturn \"\", io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.DecodeMNC(i.Payload[2:4]), nil\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMNC returns MNC in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMNC() string {\n\tv, _ := i.MNC()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/ms-timezone.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"math\"\n\t\"time\"\n)\n\n// Timezone adjustment definitions.\nconst (\n\tTimeAdjustNoDaylightSaving uint8 = iota\n\tTimeAdjustDaylightSavingOneHour\n\tTimeAdjustDaylightSavingTwoHour\n)\n\n// NewMSTimeZone creates a new MSTimeZone IE.\nfunc NewMSTimeZone(tz time.Duration, daylightSaving uint8) *IE {\n\ti := New(MSTimeZone, make([]byte, 2))\n\tmin := tz.Minutes() / 15\n\tabsMin := int(math.Abs(min))\n\thex := byte(((absMin % 10) << 4) | (absMin / 10))\n\tif min < 0 {\n\t\thex |= 0x08\n\t}\n\ti.Payload[0] = hex\n\ti.Payload[1] = daylightSaving & 0x03\n\n\treturn i\n}\n\n// TimeZone returns TimeZone in time.Duration if the type of IE matches.\nfunc (i *IE) TimeZone() (time.Duration, error) {\n\tif i.Type != MSTimeZone {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tunsigned := i.Payload[0] & 0xf7\n\tdec := int((unsigned >> 4) + (unsigned&0x0f)*10)\n\tif (i.Payload[0]&0x08)>>3 == 1 {\n\t\tdec *= -1\n\t}\n\n\treturn time.Duration(dec*15) * time.Minute, nil\n}\n\n// MustTimeZone returns TimeZone in time.Duration if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTimeZone() time.Duration {\n\tv, _ := i.TimeZone()\n\treturn v\n}\n\n// DaylightSaving returns DaylightSaving in uint8 if the type of IE matches.\nfunc (i *IE) DaylightSaving() (uint8, error) {\n\tif i.Type != MSTimeZone {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[1], nil\n}\n\n// MustDaylightSaving returns DaylightSaving in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustDaylightSaving() uint8 {\n\tv, _ := i.DaylightSaving()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/ms-validated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewMSValidated creates a new MSValidated IE.\nfunc NewMSValidated(validated bool) *IE {\n\tif validated {\n\t\treturn newUint8ValIE(MSValidated, 0xff)\n\t}\n\treturn newUint8ValIE(MSValidated, 0xfe)\n}\n\n// MSValidated returns MSValidated in bool if type matches.\nfunc (i *IE) MSValidated() bool {\n\tif i.Type != MSValidated {\n\t\treturn false\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn false\n\t}\n\n\treturn i.Payload[0]%2 == 1\n}\n"
  },
  {
    "path": "gtpv1/ie/msisdn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewMSISDN creates a new MSISDN IE.\nfunc NewMSISDN(msisdn string) *IE {\n\ti, err := utils.StrToSwappedBytes(\"19\"+msisdn, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn New(MSISDN, i)\n}\n\n// MSISDN returns MSISDN value if type matches.\nfunc (i *IE) MSISDN() (string, error) {\n\tif i.Type != MSISDN {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.SwappedBytesToStr(i.Payload[1:], false), nil\n}\n\n// MustMSISDN returns MSISDN in string if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMSISDN() string {\n\tv, _ := i.MSISDN()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/nsapi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewNSAPI creates a new NSAPI IE.\nfunc NewNSAPI(nsapi uint8) *IE {\n\treturn newUint8ValIE(NSAPI, nsapi)\n}\n\n// NSAPI returns NSAPI value if type matches.\nfunc (i *IE) NSAPI() (uint8, error) {\n\tif i.Type != NSAPI {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustNSAPI returns NSAPI in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustNSAPI() uint8 {\n\tv, _ := i.NSAPI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/p-tmsi-signature.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewPTMSISignature creates a new PTMSISignature IE.\nfunc NewPTMSISignature(sig uint32) *IE {\n\treturn New(PTMSISignature, utils.Uint32To24(sig))\n}\n\n// PTMSISignature returns PTMSISignature value in uint32 if type matches.\nfunc (i *IE) PTMSISignature() (uint32, error) {\n\tif i.Type != PTMSISignature {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.Uint24To32(i.Payload), nil\n}\n\n// MustPTMSISignature returns PTMSISignature in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPTMSISignature() uint32 {\n\tv, _ := i.PTMSISignature()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/p-tmsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewPacketTMSI creates a new PacketTMSI IE.\nfunc NewPacketTMSI(ptmsi uint32) *IE {\n\treturn newUint32ValIE(PacketTMSI, ptmsi)\n}\n\n// PacketTMSI returns PacketTMSI value in uint32 if type matches.\nfunc (i *IE) PacketTMSI() (uint32, error) {\n\tif i.Type != PacketTMSI {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload), nil\n}\n\n// MustPacketTMSI returns PacketTMSI in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPacketTMSI() uint32 {\n\tv, _ := i.PacketTMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/pco.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"encoding/binary\"\n\n// ConfigurationProtocolOption represents a Configuration protocol option in PCO.\ntype ConfigurationProtocolOption struct {\n\tProtocolID uint16\n\tLength     uint8\n\tContents   []byte\n}\n\n// NewConfigurationProtocolOption creates a new ConfigurationProtocolOption.\nfunc NewConfigurationProtocolOption(pid uint16, contents []byte) *ConfigurationProtocolOption {\n\tc := &ConfigurationProtocolOption{\n\t\tProtocolID: pid,\n\t\tLength:     uint8(len(contents)),\n\t\tContents:   contents,\n\t}\n\treturn c\n}\n\n// Marshal serializes ConfigurationProtocolOption.\nfunc (c *ConfigurationProtocolOption) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes ConfigurationProtocolOption.\nfunc (c *ConfigurationProtocolOption) MarshalTo(b []byte) error {\n\tbinary.BigEndian.PutUint16(b[0:2], c.ProtocolID)\n\tb[2] = c.Length\n\tif c.Length != 0 {\n\t\tcopy(b[3:], c.Contents)\n\t}\n\n\treturn nil\n}\n\n// ParseConfigurationProtocolOption decodes ConfigurationProtocolOption.\nfunc ParseConfigurationProtocolOption(b []byte) (*ConfigurationProtocolOption, error) {\n\tc := &ConfigurationProtocolOption{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes into ConfigurationProtocolOption.\nfunc (c *ConfigurationProtocolOption) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn ErrTooShortToParse\n\t}\n\tc.ProtocolID = binary.BigEndian.Uint16(b[0:2])\n\tc.Length = b[2]\n\tif c.Length != 0 && l >= 3+int(c.Length) {\n\t\tc.Contents = make([]byte, c.Length)\n\t\tcopy(c.Contents, b[3:3+int(c.Length)])\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of ConfigurationProtocolOption in int.\nfunc (c *ConfigurationProtocolOption) MarshalLen() int {\n\treturn 3 + len(c.Contents)\n}\n\n// PCOPayload is a Payload of ProtocolConfigurationPayload IE.\ntype PCOPayload struct {\n\tConfigurationProtocol        uint8\n\tConfigurationProtocolOptions []*ConfigurationProtocolOption\n}\n\n// NewPCOPayload creates a new PCOPayload.\nfunc NewPCOPayload(configProto uint8, opts ...*ConfigurationProtocolOption) *PCOPayload {\n\tp := &PCOPayload{ConfigurationProtocol: configProto}\n\tp.ConfigurationProtocolOptions = append(p.ConfigurationProtocolOptions, opts...)\n\n\treturn p\n}\n\n// Marshal serializes PCOPayload.\nfunc (p *PCOPayload) Marshal() ([]byte, error) {\n\tb := make([]byte, p.MarshalLen())\n\tif err := p.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes PCOPayload.\nfunc (p *PCOPayload) MarshalTo(b []byte) error {\n\tb[0] = (p.ConfigurationProtocol & 0x07) | 0x80\n\toffset := 1\n\tfor _, opt := range p.ConfigurationProtocolOptions {\n\t\tif err := opt.MarshalTo(b[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += opt.MarshalLen()\n\t}\n\n\treturn nil\n}\n\n// ParsePCOPayload decodes PCOPayload.\nfunc ParsePCOPayload(b []byte) (*PCOPayload, error) {\n\tp := &PCOPayload{}\n\tif err := p.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn p, nil\n}\n\n// UnmarshalBinary decodes given bytes into PCOPayload.\nfunc (p *PCOPayload) UnmarshalBinary(b []byte) error {\n\tif len(b) == 0 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\tp.ConfigurationProtocol = b[0] & 0x07\n\n\toffset := 1\n\tfor {\n\t\tif offset >= len(b) {\n\t\t\treturn nil\n\t\t}\n\t\topt, err := ParseConfigurationProtocolOption(b[offset:])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tp.ConfigurationProtocolOptions = append(p.ConfigurationProtocolOptions, opt)\n\t\toffset += opt.MarshalLen()\n\t}\n}\n\n// MarshalLen returns the serial length of PCOPayload in int.\nfunc (p *PCOPayload) MarshalLen() int {\n\tl := 1\n\tfor _, opt := range p.ConfigurationProtocolOptions {\n\t\tl += opt.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// NewProtocolConfigurationOptions creates a new ProtocolConfigurationOptions IE.\nfunc NewProtocolConfigurationOptions(configProto uint8, options ...*ConfigurationProtocolOption) *IE {\n\tpco := NewPCOPayload(configProto, options...)\n\n\ti := New(ProtocolConfigurationOptions, make([]byte, pco.MarshalLen()))\n\tif err := pco.MarshalTo(i.Payload); err != nil {\n\t\treturn nil\n\t}\n\n\treturn i\n}\n\n// ProtocolConfigurationOptions returns ProtocolConfigurationOptions in\n// PCOPayload type if the type of IE matches.\nfunc (i *IE) ProtocolConfigurationOptions() (*PCOPayload, error) {\n\tif i.Type != ProtocolConfigurationOptions {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\n\tpco, err := ParsePCOPayload(i.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn pco, nil\n}\n\n// MustProtocolConfigurationOptions returns ProtocolConfigurationOptions in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustProtocolConfigurationOptions() *PCOPayload {\n\tv, _ := i.ProtocolConfigurationOptions()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/private-extension.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewPrivateExtension creates a new PrivateExtension IE from string.\nfunc NewPrivateExtension(id uint16, val []byte) *IE {\n\ti := New(PrivateExtension, make([]byte, 2+len(val)))\n\tbinary.BigEndian.PutUint16(i.Payload[:2], id)\n\tcopy(i.Payload[2:], val)\n\treturn i\n}\n\n// PrivateExtension returns PrivateExtension value if type matches.\nfunc (i *IE) PrivateExtension() ([]byte, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustPrivateExtension returns PrivateExtension in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPrivateExtension() []byte {\n\tv, _ := i.PrivateExtension()\n\treturn v\n}\n\n// ExtensionIdentifier returns ExtensionIdentifier value in uint16 if type matches.\nfunc (i *IE) ExtensionIdentifier() (uint16, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(i.Payload[:2]), nil\n}\n\n// MustExtensionIdentifier returns ExtensionIdentifier in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtensionIdentifier() uint16 {\n\tv, _ := i.ExtensionIdentifier()\n\treturn v\n}\n\n// ExtensionValue returns ExtensionValue value if type matches.\nfunc (i *IE) ExtensionValue() ([]byte, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[2:], nil\n}\n\n// MustExtensionValue returns ExtensionValue in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustExtensionValue() []byte {\n\tv, _ := i.ExtensionValue()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/qos-profile.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewQoSProfile creates a new QoSProfile IE.\n//\n// XXX - NOT Fully implemented. Users need to put the whole payload in []byte.\nfunc NewQoSProfile(payload []byte) *IE {\n\treturn New(QoSProfile, payload)\n}\n\n// QoSProfile returns QoSProfile if type matches.\n//\n// XXX - NOT Fully implemented. This method just returns the whole payload in []byte.\nfunc (i *IE) QoSProfile() ([]byte, error) {\n\tif i.Type != QoSProfile {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustQoSProfile returns QoSProfile in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustQoSProfile() []byte {\n\tv, _ := i.QoSProfile()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/rac.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// RAC returns RAC value if type matches.\nfunc (i *IE) RAC() (uint8, error) {\n\tswitch i.Type {\n\tcase RouteingAreaIdentity:\n\t\tif len(i.Payload) < 6 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[5], nil\n\tcase UserLocationInformation:\n\t\tif len(i.Payload) < 7 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\tif i.Payload[0] == locTypeRAI {\n\t\t\treturn i.Payload[6], nil\n\t\t}\n\t}\n\treturn 0, &InvalidTypeError{Type: i.Type}\n}\n\n// MustRAC returns RAC in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRAC() uint8 {\n\tv, _ := i.RAC()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/rai.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewRouteingAreaIdentity creates a new RouteingAreaIdentity IE.\nfunc NewRouteingAreaIdentity(mcc, mnc string, lac uint16, rac uint8) *IE {\n\tmc, err := utils.StrToSwappedBytes(mcc, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\tmn, err := utils.StrToSwappedBytes(mnc, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\trai := New(\n\t\tRouteingAreaIdentity,\n\t\tmake([]byte, 6),\n\t)\n\tcopy(rai.Payload[0:2], mc)\n\trai.Payload[2] = mn[0]\n\tbinary.BigEndian.PutUint16(rai.Payload[3:5], lac)\n\trai.Payload[5] = rac\n\n\treturn rai\n}\n\n// RouteingAreaIdentity returns RouteingAreaIdentity value if type matches.\nfunc (i *IE) RouteingAreaIdentity() ([]byte, error) {\n\tif i.Type != RouteingAreaIdentity {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustRouteingAreaIdentity returns RouteingAreaIdentity in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRouteingAreaIdentity() []byte {\n\tv, _ := i.RouteingAreaIdentity()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/rai_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"testing\"\n)\n\nfunc TestRouteingAreaIdentity(t *testing.T) {\n\tt.Run(\"Routeing Area Identity\", func(t *testing.T) {\n\t\tie := NewRouteingAreaIdentity(\"123\", \"45\", 111, 222)\n\n\t\trac := ie.MustRAC()\n\t\tif rac != 222 {\n\t\t\tt.Errorf(\"wrong rac, got %v\", rac)\n\t\t}\n\n\t\tlac := ie.MustLAC()\n\t\tif lac != 111 {\n\t\t\tt.Errorf(\"wrong lac, got %v\", lac)\n\t\t}\n\n\t\tmcc := ie.MustMCC()\n\t\tif mcc != \"123\" {\n\t\t\tt.Errorf(\"wrong mcc, got %v\", mcc)\n\t\t}\n\n\t\tmnc := ie.MustMNC()\n\t\tif mnc != \"45\" {\n\t\t\tt.Errorf(\"wrong mnc, got %v\", mnc)\n\t\t}\n\n\t})\n}\n"
  },
  {
    "path": "gtpv1/ie/ranap-cause.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewRANAPCause creates a new RANAPCause IE.\nfunc NewRANAPCause(cause uint8) *IE {\n\treturn newUint8ValIE(RANAPCause, cause)\n}\n\n// RANAPCause returns RANAPCause in uint8 if type matches.\nfunc (i *IE) RANAPCause() (uint8, error) {\n\tif i.Type != RANAPCause {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustRANAPCause returns RANAPCause in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRANAPCause() uint8 {\n\tv, _ := i.RANAPCause()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/rat-type.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewRATType creates a new RATType IE.\nfunc NewRATType(ratType uint8) *IE {\n\treturn New(\n\t\tRATType,\n\t\t[]byte{ratType},\n\t)\n}\n\n// RATType returns RATType value if type matches.\nfunc (i *IE) RATType() (uint8, error) {\n\tif i.Type != RATType {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustRATType returns RATType in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRATType() uint8 {\n\tv, _ := i.RATType()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/recovery.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewRecovery creates a new Recovery IE.\nfunc NewRecovery(recovery uint8) *IE {\n\treturn newUint8ValIE(Recovery, recovery)\n}\n\n// Recovery returns Recovery value if type matches.\nfunc (i *IE) Recovery() (uint8, error) {\n\tif i.Type != Recovery {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustRecovery returns Recovery in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRecovery() uint8 {\n\tv, _ := i.Recovery()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/reordering-required.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewReorderingRequired creates a new ReorderingRequired IE.\nfunc NewReorderingRequired(required bool) *IE {\n\tif required {\n\t\treturn newUint8ValIE(ReorderingRequired, 0xff)\n\t}\n\treturn newUint8ValIE(ReorderingRequired, 0xfe)\n}\n\n// ReorderingRequired returns ReorderingRequired or not if type matches.\nfunc (i *IE) ReorderingRequired() bool {\n\tif i.Type != ReorderingRequired {\n\t\treturn false\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn false\n\t}\n\n\treturn i.Payload[0]&0x01 == 1\n}\n"
  },
  {
    "path": "gtpv1/ie/selection-mode.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewSelectionMode creates a new SelectionMode IE.\n// Note that exactly one of the parameters should be set to true.\n// Otherwise, you'll get the unexpected result.\nfunc NewSelectionMode(mode uint8) *IE {\n\treturn newUint8ValIE(SelectionMode, mode)\n}\n\n// SelectionMode returns SelectionMode value if type matches.\nfunc (i *IE) SelectionMode() (uint8, error) {\n\tif i.Type != SelectionMode {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// MustSelectionMode returns SelectionMode in uint8 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustSelectionMode() uint8 {\n\tv, _ := i.SelectionMode()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/teardown-ind.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewTeardownInd creates a new TeardownInd IE.\nfunc NewTeardownInd(teardown bool) *IE {\n\tif teardown {\n\t\treturn newUint8ValIE(TeardownInd, 0xff)\n\t}\n\treturn newUint8ValIE(TeardownInd, 0xfe)\n}\n\n// TeardownInd returns TeardownInd in bool if type matches.\nfunc (i *IE) TeardownInd() bool {\n\tif i.Type != TeardownInd {\n\t\treturn false\n\t}\n\tif len(i.Payload) == 0 {\n\t\treturn false\n\t}\n\n\treturn i.Payload[0]%2 == 1\n}\n"
  },
  {
    "path": "gtpv1/ie/teid.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewTEIDDataI creates a new TEIDDataI IE.\nfunc NewTEIDDataI(teid uint32) *IE {\n\treturn newUint32ValIE(TEIDDataI, teid)\n}\n\n// NewTEIDCPlane creates a new TEID C-Plane IE.\nfunc NewTEIDCPlane(teid uint32) *IE {\n\treturn newUint32ValIE(TEIDCPlane, teid)\n}\n\n// NewTEIDDataII creates a new TEIDDataII IE.\nfunc NewTEIDDataII(teid uint32) *IE {\n\treturn newUint32ValIE(TEIDDataII, teid)\n}\n\n// TEID returns TEID value if type matches.\nfunc (i *IE) TEID() (uint32, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\tswitch i.Type {\n\tcase TEIDCPlane, TEIDDataI, TEIDDataII:\n\t\treturn binary.BigEndian.Uint32(i.Payload), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustTEID returns TEID in uint32 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTEID() uint32 {\n\tv, _ := i.TEID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/uli-timestamp.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"time\"\n)\n\n// NewULITimestamp creates a new ULITimestamp IE.\nfunc NewULITimestamp(ts time.Time) *IE {\n\tu64sec := uint64(ts.Sub(time.Date(1900, time.January, 1, 0, 0, 0, 0, time.UTC))) / 1000000000\n\treturn newUint32ValIE(ULITimestamp, uint32(u64sec))\n}\n\n// Timestamp returns Timestamp in time.Time if the type of IE matches.\nfunc (i *IE) Timestamp() (time.Time, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn time.Time{}, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase ULITimestamp:\n\t\treturn time.Unix(int64(binary.BigEndian.Uint32(i.Payload)-2208988800), 0), nil\n\tdefault:\n\t\treturn time.Time{}, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustTimestamp returns Timestamp in time.Time if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTimestamp() time.Time {\n\tv, _ := i.Timestamp()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/uli.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// UserLocationInformation GeographicLocationType definitions.\nconst (\n\tlocTypeCGI uint8 = iota\n\tlocTypeSAI\n\tlocTypeRAI\n)\n\n// NewUserLocationInformationWithCGI creates a new UserLocationInformation IE with LAC.\nfunc NewUserLocationInformationWithCGI(mcc, mnc string, lac, cgi uint16) *IE {\n\tplmn, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tuli := New(\n\t\tUserLocationInformation,\n\t\tmake([]byte, 8),\n\t)\n\tuli.Payload[0] = locTypeCGI\n\tcopy(uli.Payload[1:4], plmn)\n\tbinary.BigEndian.PutUint16(uli.Payload[4:6], lac)\n\tbinary.BigEndian.PutUint16(uli.Payload[6:8], cgi)\n\n\treturn uli\n}\n\n// NewUserLocationInformationWithSAI creates a new UserLocationInformation IE with LAC.\nfunc NewUserLocationInformationWithSAI(mcc, mnc string, lac, sac uint16) *IE {\n\tplmn, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tuli := New(\n\t\tUserLocationInformation,\n\t\tmake([]byte, 8),\n\t)\n\tuli.Payload[0] = locTypeSAI\n\tcopy(uli.Payload[1:4], plmn)\n\tbinary.BigEndian.PutUint16(uli.Payload[4:6], lac)\n\tbinary.BigEndian.PutUint16(uli.Payload[6:8], sac)\n\n\treturn uli\n}\n\n// NewUserLocationInformationWithRAI creates a new UserLocationInformation IE with LAC.\nfunc NewUserLocationInformationWithRAI(mcc, mnc string, lac uint16, rac uint8) *IE {\n\tplmn, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tuli := New(\n\t\tUserLocationInformation,\n\t\tmake([]byte, 7),\n\t)\n\tuli.Payload[0] = locTypeRAI\n\tcopy(uli.Payload[1:4], plmn)\n\tbinary.BigEndian.PutUint16(uli.Payload[4:6], lac)\n\tuli.Payload[6] = rac\n\n\treturn uli\n}\n\n// UserLocationInformation returns UserLocationInformation value if type matches.\nfunc (i *IE) UserLocationInformation() ([]byte, error) {\n\tif i.Type != UserLocationInformation {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.Payload, nil\n}\n\n// MustUserLocationInformation returns UserLocationInformation in []byte if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustUserLocationInformation() []byte {\n\tv, _ := i.UserLocationInformation()\n\treturn v\n}\n\n// CGI returns CGI value if type matches.\nfunc (i *IE) CGI() (uint16, error) {\n\tif i.Type != UserLocationInformation {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tif i.Payload[0] == locTypeCGI {\n\t\tif len(i.Payload) < 8 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[6:8]), nil\n\t}\n\treturn 0, &InvalidTypeError{Type: i.Type}\n}\n\n// MustCGI returns CGI in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCGI() uint16 {\n\tv, _ := i.CGI()\n\treturn v\n}\n\n// SAC returns SAC value if type matches.\nfunc (i *IE) SAC() (uint16, error) {\n\tif i.Type != UserLocationInformation {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tif i.Payload[0] == locTypeSAI {\n\t\tif len(i.Payload) < 8 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[6:8]), nil\n\t}\n\treturn 0, &InvalidTypeError{Type: i.Type}\n}\n\n// MustSAC returns SAC in uint16 if type matches.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustSAC() uint16 {\n\tv, _ := i.SAC()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv1/ie/uli_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"testing\"\n)\n\nfunc TestUserLocationInformationWithCGI(t *testing.T) {\n\tt.Run(\"Test UserLocationInformation with CGI\", func(t *testing.T) {\n\t\tie := NewUserLocationInformationWithCGI(\"123\", \"45\", 111, 222)\n\n\t\tcgi := ie.MustCGI()\n\t\tif cgi != 222 {\n\t\t\tt.Errorf(\"wrong cgi, got %v\", cgi)\n\t\t}\n\n\t\tlac := ie.MustLAC()\n\t\tif lac != 111 {\n\t\t\tt.Errorf(\"wrong lac, got %v\", lac)\n\t\t}\n\n\t\tmcc := ie.MustMCC()\n\t\tif mcc != \"123\" {\n\t\t\tt.Errorf(\"wrong mcc, got %v\", mcc)\n\t\t}\n\n\t\tmnc := ie.MustMNC()\n\t\tif mnc != \"45\" {\n\t\t\tt.Errorf(\"wrong mnc, got %v\", mnc)\n\t\t}\n\t})\n\n\tt.Run(\"Test UserLocationInformation with CGI (3-digit MNC)\", func(t *testing.T) {\n\t\tie := NewUserLocationInformationWithCGI(\"123\", \"456\", 111, 222)\n\n\t\tcgi := ie.MustCGI()\n\t\tif cgi != 222 {\n\t\t\tt.Errorf(\"wrong cgi, got %v\", cgi)\n\t\t}\n\n\t\tlac := ie.MustLAC()\n\t\tif lac != 111 {\n\t\t\tt.Errorf(\"wrong lac, got %v\", lac)\n\t\t}\n\n\t\tmcc := ie.MustMCC()\n\t\tif mcc != \"123\" {\n\t\t\tt.Errorf(\"wrong mcc, got %v\", mcc)\n\t\t}\n\n\t\tmnc := ie.MustMNC()\n\t\tif mnc != \"456\" {\n\t\t\tt.Errorf(\"wrong mnc, got %v\", mnc)\n\t\t}\n\t})\n}\n\nfunc TestUserLocationInformationWithRAI(t *testing.T) {\n\tt.Run(\"Test UserLocationInformation with RAI\", func(t *testing.T) {\n\t\tie := NewUserLocationInformationWithRAI(\"123\", \"45\", 111, 222)\n\n\t\trac := ie.MustRAC()\n\t\tif rac != 222 {\n\t\t\tt.Errorf(\"wrong rac, got %v\", rac)\n\t\t}\n\n\t\tlac := ie.MustLAC()\n\t\tif lac != 111 {\n\t\t\tt.Errorf(\"wrong lac, got %v\", lac)\n\t\t}\n\n\t\tmcc := ie.MustMCC()\n\t\tif mcc != \"123\" {\n\t\t\tt.Errorf(\"wrong mcc, got %v\", mcc)\n\t\t}\n\n\t\tmnc := ie.MustMNC()\n\t\tif mnc != \"45\" {\n\t\t\tt.Errorf(\"wrong mnc, got %v\", mnc)\n\t\t}\n\t})\n}\n\nfunc TestUserLocationInformationWithSAI(t *testing.T) {\n\tt.Run(\"Test UserLocationInformation with SAI\", func(t *testing.T) {\n\t\tie := NewUserLocationInformationWithSAI(\"123\", \"45\", 111, 222)\n\n\t\tsac := ie.MustSAC()\n\t\tif sac != 222 {\n\t\t\tt.Errorf(\"wrong sac, got %v\", sac)\n\t\t}\n\n\t\tlac := ie.MustLAC()\n\t\tif lac != 111 {\n\t\t\tt.Errorf(\"wrong lac, got %v\", lac)\n\t\t}\n\n\t\tmcc := ie.MustMCC()\n\t\tif mcc != \"123\" {\n\t\t\tt.Errorf(\"wrong mcc, got %v\", mcc)\n\t\t}\n\n\t\tmnc := ie.MustMNC()\n\t\tif mnc != \"45\" {\n\t\t\tt.Errorf(\"wrong mnc, got %v\", mnc)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv1/logger.go",
    "content": "// Copyright 2019 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"sync\"\n)\n\nvar (\n\tlogger = log.New(os.Stderr, \"\", log.LstdFlags)\n\tlogMu  sync.Mutex\n)\n\n// SetLogger replaces the standard logger with arbitrary *log.Logger.\n//\n// This package prints just informational logs from goroutines working background\n// that might help developers test the program but can be ignored safely. More\n// important ones that needs any action by caller would be returned as errors.\nfunc SetLogger(l *log.Logger) {\n\tif l == nil {\n\t\tlog.Println(\"Don't pass nil to SetLogger: use DisableLogging instead.\")\n\t}\n\n\tsetLogger(l)\n}\n\n// EnableLogging enables the logging from the package.\n// If l is nil, it uses default logger provided by the package.\n// Logging is enabled by default.\n//\n// See also: SetLogger.\nfunc EnableLogging(l *log.Logger) {\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tsetLogger(l)\n}\n\n// DisableLogging disables the logging from the package.\n// Logging is enabled by default.\nfunc DisableLogging() {\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tlogger.SetOutput(io.Discard)\n}\n\nfunc setLogger(l *log.Logger) {\n\tif l == nil {\n\t\tl = log.New(os.Stderr, \"\", log.LstdFlags)\n\t}\n\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tlogger = l\n}\n\nfunc logf(format string, v ...interface{}) {\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tlogger.Printf(format, v...)\n}\n"
  },
  {
    "path": "gtpv1/message/create-pdp-context-req.go",
    "content": "// Copyright 2019-2023 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// CreatePDPContextRequest is a CreatePDPContextRequest Header and its IEs above.\ntype CreatePDPContextRequest struct {\n\t*Header\n\tIMSI                               *ie.IE\n\tRAI                                *ie.IE\n\tRecovery                           *ie.IE\n\tSelectionMode                      *ie.IE\n\tTEIDDataI                          *ie.IE\n\tTEIDCPlane                         *ie.IE\n\tNSAPI                              *ie.IE\n\tLinkedNSAPI                        *ie.IE\n\tChargingCharacteristics            *ie.IE\n\tTraceReference                     *ie.IE\n\tTraceType                          *ie.IE\n\tEndUserAddress                     *ie.IE\n\tAPN                                *ie.IE\n\tPCO                                *ie.IE\n\tSGSNAddressForSignalling           *ie.IE\n\tSGSNAddressForUserTraffic          *ie.IE\n\tMSISDN                             *ie.IE\n\tQoSProfile                         *ie.IE\n\tTFT                                *ie.IE\n\tTriggerID                          *ie.IE\n\tOMCIdentity                        *ie.IE\n\tCommonFlags                        *ie.IE\n\tAPNRestriction                     *ie.IE\n\tRATType                            *ie.IE\n\tUserLocationInformation            *ie.IE\n\tMSTimeZone                         *ie.IE\n\tIMEI                               *ie.IE\n\tCAMELChargingInformationContainer  *ie.IE\n\tAdditionalTraceInfo                *ie.IE\n\tCorrelationID                      *ie.IE\n\tEvolvedARPI                        *ie.IE\n\tExtendedCommonFlags                *ie.IE\n\tUCI                                *ie.IE\n\tAPNAMBR                            *ie.IE\n\tSignallingPriorityIndication       *ie.IE\n\tCNOperatorSelectionEntity          *ie.IE\n\tMappedUEUsageType                  *ie.IE\n\tUPFunctionSelectionIndicationFlags *ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewCreatePDPContextRequest creates a new GTPv1 CreatePDPContextRequest.\nfunc NewCreatePDPContextRequest(teid uint32, seq uint16, ies ...*ie.IE) *CreatePDPContextRequest {\n\tc := &CreatePDPContextRequest{\n\t\tHeader: NewHeader(0x32, MsgTypeCreatePDPContextRequest, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tc.RAI = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.SelectionMode:\n\t\t\tc.SelectionMode = i\n\t\tcase ie.TEIDDataI:\n\t\t\tc.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tc.TEIDCPlane = i\n\t\tcase ie.NSAPI:\n\t\t\tif c.NSAPI == nil {\n\t\t\t\tc.NSAPI = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.LinkedNSAPI == nil {\n\t\t\t\tc.LinkedNSAPI = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\tcase ie.ChargingCharacteristics:\n\t\t\tc.ChargingCharacteristics = i\n\t\tcase ie.TraceReference:\n\t\t\tc.TraceReference = i\n\t\tcase ie.TraceType:\n\t\t\tc.TraceType = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.AccessPointName:\n\t\t\tc.APN = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.SGSNAddressForSignalling == nil {\n\t\t\t\tc.SGSNAddressForSignalling = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.SGSNAddressForUserTraffic == nil {\n\t\t\t\tc.SGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\tcase ie.MSISDN:\n\t\t\tc.MSISDN = i\n\t\tcase ie.QoSProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.TrafficFlowTemplate:\n\t\t\tc.TFT = i\n\t\tcase ie.TriggerID:\n\t\t\tc.TriggerID = i\n\t\tcase ie.OMCIdentity:\n\t\t\tc.OMCIdentity = i\n\t\tcase ie.CommonFlags:\n\t\t\tc.CommonFlags = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.UserLocationInformation = i\n\t\tcase ie.MSTimeZone:\n\t\t\tc.MSTimeZone = i\n\t\tcase ie.IMEISV:\n\t\t\tc.IMEI = i\n\t\tcase ie.CAMELChargingInformationContainer:\n\t\t\tc.CAMELChargingInformationContainer = i\n\t\tcase ie.AdditionalTraceInfo:\n\t\t\tc.AdditionalTraceInfo = i\n\t\tcase ie.CorrelationID:\n\t\t\tc.CorrelationID = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tc.EvolvedARPI = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\tc.ExtendedCommonFlags = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.APNAMBR = i\n\t\tcase ie.SignallingPriorityIndication:\n\t\t\tc.SignallingPriorityIndication = i\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tc.CNOperatorSelectionEntity = i\n\t\tcase ie.MappedUEUsageType:\n\t\t\tc.MappedUEUsageType = i\n\t\tcase ie.UPFunctionSelectionIndicationFlags:\n\t\t\tc.UPFunctionSelectionIndicationFlags = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal returns the byte sequence generated from a CreatePDPContextRequest.\nfunc (c *CreatePDPContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (c *CreatePDPContextRequest) MarshalTo(b []byte) error {\n\tif len(b) < c.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RAI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SelectionMode; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDDataI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NSAPI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedNSAPI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingCharacteristics; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TraceReference; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TraceType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForSignalling; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MSISDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TFT; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TriggerID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.OMCIdentity; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UserLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MSTimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IMEI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CAMELChargingInformationContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AdditionalTraceInfo; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CorrelationID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EvolvedARPI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedCommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNAMBR; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SignallingPriorityIndication; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CNOperatorSelectionEntity; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MappedUEUsageType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UPFunctionSelectionIndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreatePDPContextRequest decodes a given byte sequence as a CreatePDPContextRequest.\nfunc ParseCreatePDPContextRequest(b []byte) (*CreatePDPContextRequest, error) {\n\tc := &CreatePDPContextRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a CreatePDPContextRequest.\nfunc (c *CreatePDPContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tc.RAI = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.SelectionMode:\n\t\t\tc.SelectionMode = i\n\t\tcase ie.TEIDDataI:\n\t\t\tc.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tc.TEIDCPlane = i\n\t\tcase ie.NSAPI:\n\t\t\tif c.NSAPI == nil {\n\t\t\t\tc.NSAPI = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.LinkedNSAPI == nil {\n\t\t\t\tc.LinkedNSAPI = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\tcase ie.ChargingCharacteristics:\n\t\t\tc.ChargingCharacteristics = i\n\t\tcase ie.TraceReference:\n\t\t\tc.TraceReference = i\n\t\tcase ie.TraceType:\n\t\t\tc.TraceType = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.AccessPointName:\n\t\t\tc.APN = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.SGSNAddressForSignalling == nil {\n\t\t\t\tc.SGSNAddressForSignalling = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.SGSNAddressForUserTraffic == nil {\n\t\t\t\tc.SGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\tcase ie.MSISDN:\n\t\t\tc.MSISDN = i\n\t\tcase ie.QoSProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.TrafficFlowTemplate:\n\t\t\tc.TFT = i\n\t\tcase ie.TriggerID:\n\t\t\tc.TriggerID = i\n\t\tcase ie.OMCIdentity:\n\t\t\tc.OMCIdentity = i\n\t\tcase ie.CommonFlags:\n\t\t\tc.CommonFlags = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.UserLocationInformation = i\n\t\tcase ie.MSTimeZone:\n\t\t\tc.MSTimeZone = i\n\t\tcase ie.IMEISV:\n\t\t\tc.IMEI = i\n\t\tcase ie.CAMELChargingInformationContainer:\n\t\t\tc.CAMELChargingInformationContainer = i\n\t\tcase ie.AdditionalTraceInfo:\n\t\t\tc.AdditionalTraceInfo = i\n\t\tcase ie.CorrelationID:\n\t\t\tc.CorrelationID = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tc.EvolvedARPI = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\tc.ExtendedCommonFlags = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.APNAMBR = i\n\t\tcase ie.SignallingPriorityIndication:\n\t\t\tc.SignallingPriorityIndication = i\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tc.CNOperatorSelectionEntity = i\n\t\tcase ie.MappedUEUsageType:\n\t\t\tc.MappedUEUsageType = i\n\t\tcase ie.UPFunctionSelectionIndicationFlags:\n\t\t\tc.UPFunctionSelectionIndicationFlags = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (c *CreatePDPContextRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RAI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SelectionMode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NSAPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedNSAPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingCharacteristics; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TraceReference; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TraceType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForSignalling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MSISDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TFT; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TriggerID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.OMCIdentity; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UserLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MSTimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IMEI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CAMELChargingInformationContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AdditionalTraceInfo; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CorrelationID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EvolvedARPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedCommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNAMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SignallingPriorityIndication; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CNOperatorSelectionEntity; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MappedUEUsageType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UPFunctionSelectionIndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreatePDPContextRequest) SetLength() {\n\tc.Length = uint16(c.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreatePDPContextRequest) MessageTypeName() string {\n\treturn \"Create PDP Context Request\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (c *CreatePDPContextRequest) TEID() uint32 {\n\treturn c.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/create-pdp-context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreatePDPContextRequest into bytes.\n//\n// Deprecated: use CreatePDPContextRequest.Marshal instead.\nfunc (c *CreatePDPContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"CreatePDPContextRequest.Serialize is deprecated. use CreatePDPContextRequest.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreatePDPContextRequest into bytes given as b.\n//\n// Deprecated: use CreatePDPContextRequest.MarshalTo instead.\nfunc (c *CreatePDPContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"CreatePDPContextRequest.SerializeTo is deprecated. use CreatePDPContextRequest.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreatePDPContextRequest decodes bytes as CreatePDPContextRequest.\n//\n// Deprecated: use ParseCreatePDPContextRequest instead.\nfunc DecodeCreatePDPContextRequest(b []byte) (*CreatePDPContextRequest, error) {\n\tlog.Println(\"DecodeCreatePDPContextRequest is deprecated. use ParseCreatePDPContextRequest instead\")\n\treturn ParseCreatePDPContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as CreatePDPContextRequest.\n//\n// Deprecated: use CreatePDPContextRequest.UnmarshalBinary instead.\nfunc (c *CreatePDPContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreatePDPContextRequest.DecodeFromBytes is deprecated. use CreatePDPContextRequest.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreatePDPContextRequest.\n//\n// Deprecated: use CreatePDPContextRequest.MarshalLen instead.\nfunc (c *CreatePDPContextRequest) Len() int {\n\tlog.Println(\"CreatePDPContextRequest.Len is deprecated. use CreatePDPContextRequest.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/create-pdp-context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestCreatePDPContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewCreatePDPContextRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123450123456789\"),\n\t\t\t\tie.NewRouteingAreaIdentity(\"123\", \"45\", 0x1111, 0x22),\n\t\t\t\tie.NewRecovery(254),\n\t\t\t\tie.NewSelectionMode(gtpv1.SelectionModeMSorNetworkProvidedAPNSubscribedVerified),\n\t\t\t\tie.NewTEIDDataI(0xdeadbeef),\n\t\t\t\tie.NewTEIDCPlane(0xdeadbeef),\n\t\t\t\tie.NewNSAPI(5),\n\t\t\t\tie.NewEndUserAddressIPv4(\"\"),\n\t\t\t\tie.NewAccessPointName(\"some.apn.example\"),\n\t\t\t\tie.NewProtocolConfigurationOptions(\n\t\t\t\t\t0, ie.NewConfigurationProtocolOption(1, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\t),\n\t\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t\tie.NewMSISDN(\"123412345678\"),\n\t\t\t\tie.NewQoSProfile([]byte{0xde, 0xad, 0xbe, 0xef}), // XXX - Implement!\n\t\t\t\tie.NewCommonFlags(0, 0, 1, 0, 0, 0, 0, 0),\n\t\t\t\tie.NewRATType(gtpv1.RatTypeUTRAN),\n\t\t\t\tie.NewUserLocationInformationWithSAI(\"123\", \"45\", 0x1111, 0x2222),\n\t\t\t\tie.NewMSTimeZone(0x00, 0x00),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x10, 0x00, 0x7f, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x02, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9,\n\t\t\t\t// RAI\n\t\t\t\t0x03, 0x21, 0xf3, 0x54, 0x11, 0x11, 0x22,\n\t\t\t\t// Recovery\n\t\t\t\t0x0e, 0xfe,\n\t\t\t\t// Selection Mode\n\t\t\t\t0x0f, 0xf0,\n\t\t\t\t// TEID-U\n\t\t\t\t0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// TEID-C\n\t\t\t\t0x11, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// NSAPI\n\t\t\t\t0x14, 0x05,\n\t\t\t\t// End User Address\n\t\t\t\t0x80, 0x00, 0x02, 0xf1, 0x21,\n\t\t\t\t// APN\n\t\t\t\t0x83, 0x00, 0x11, 0x04, 0x73, 0x6f, 0x6d, 0x65, 0x03, 0x61, 0x70, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,\n\t\t\t\t// PCO\n\t\t\t\t0x84, 0x00, 0x08, 0x80, 0x00, 0x01, 0x04,\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// MSISDN\n\t\t\t\t0x86, 0x00, 0x07, 0x91, 0x21, 0x43, 0x21, 0x43,\n\t\t\t\t0x65, 0x87,\n\t\t\t\t// QoS\n\t\t\t\t0x87, 0x00, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t/* XXX - implement QoSProfile!\n\t\t\t\t0x87, 0x00, 0x0f, 0x02, 0x0b, 0x92, 0x1f, 0x73,\n\t\t\t\t0x96, 0xff, 0xff, 0x94, 0xf9, 0xff, 0xff, 0x00,\n\t\t\t\t0x6a, 0x00,\n\t\t\t\t*/\n\t\t\t\t// Common Flags\n\t\t\t\t0x94, 0x00, 0x01, 0x20,\n\t\t\t\t// RAT Type\n\t\t\t\t0x97, 0x00, 0x01, 0x01,\n\t\t\t\t// ULI\n\t\t\t\t0x98, 0x00, 0x08, 0x01, 0x21, 0xf3, 0x54, 0x11,\n\t\t\t\t0x11, 0x22, 0x22,\n\t\t\t\t// MS Time Zone\n\t\t\t\t0x99, 0x00, 0x02, 0x00, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreatePDPContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/create-pdp-context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// CreatePDPContextResponse is a CreatePDPContextResponse Header and its IEs above.\ntype CreatePDPContextResponse struct {\n\t*Header\n\tCause                         *ie.IE\n\tReorderingRequired            *ie.IE\n\tRecovery                      *ie.IE\n\tTEIDDataI                     *ie.IE\n\tTEIDCPlane                    *ie.IE\n\tNSAPI                         *ie.IE\n\tChargingID                    *ie.IE\n\tEndUserAddress                *ie.IE\n\tPCO                           *ie.IE\n\tGGSNAddressForCPlane          *ie.IE\n\tGGSNAddressForUserTraffic     *ie.IE\n\tAltGGSNAddressForCPlane       *ie.IE\n\tAltGGSNAddressForUserTraffic  *ie.IE\n\tQoSProfile                    *ie.IE\n\tChargingGatewayAddress        *ie.IE\n\tAltChargingGatewayAddress     *ie.IE\n\tCommonFlags                   *ie.IE\n\tAPNRestriction                *ie.IE\n\tMSInfoChangeReportingAction   *ie.IE\n\tBearerControlMode             *ie.IE\n\tEvolvedARPI                   *ie.IE\n\tExtendedCommonFlags           *ie.IE\n\tCSGInformationReportingAction *ie.IE\n\tAPNAMBR                       *ie.IE\n\tGGSNBackOffTime               *ie.IE\n\tExtendedCommonFlagsII         *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewCreatePDPContextResponse creates a new GTPv1 CreatePDPContextResponse.\nfunc NewCreatePDPContextResponse(teid uint32, seq uint16, ies ...*ie.IE) *CreatePDPContextResponse {\n\tc := &CreatePDPContextResponse{\n\t\tHeader: NewHeader(0x32, MsgTypeCreatePDPContextResponse, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.ReorderingRequired:\n\t\t\tc.ReorderingRequired = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.TEIDDataI:\n\t\t\tc.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tc.TEIDCPlane = i\n\t\tcase ie.NSAPI:\n\t\t\tc.NSAPI = i\n\t\tcase ie.ChargingID:\n\t\t\tc.ChargingID = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.GGSNAddressForCPlane == nil {\n\t\t\t\tc.GGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.GGSNAddressForUserTraffic == nil {\n\t\t\t\tc.GGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.AltGGSNAddressForCPlane == nil {\n\t\t\t\tc.AltGGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AltGGSNAddressForUserTraffic = i\n\t\tcase ie.QoSProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tif c.ChargingGatewayAddress == nil {\n\t\t\t\tc.ChargingGatewayAddress = i\n\t\t\t} else if c.AltChargingGatewayAddress == nil {\n\t\t\t\tc.AltChargingGatewayAddress = i\n\t\t\t}\n\t\tcase ie.CommonFlags:\n\t\t\tc.CommonFlags = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.MSInfoChangeReportingAction:\n\t\t\tc.MSInfoChangeReportingAction = i\n\t\tcase ie.BearerControlMode:\n\t\t\tc.BearerControlMode = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tc.EvolvedARPI = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\tc.ExtendedCommonFlags = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.APNAMBR = i\n\t\tcase ie.GGSNBackOffTime:\n\t\t\tc.GGSNBackOffTime = i\n\t\tcase ie.ExtendedCommonFlagsII:\n\t\t\tc.ExtendedCommonFlagsII = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal returns the byte sequence generated from a CreatePDPContextResponse.\nfunc (c *CreatePDPContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (c *CreatePDPContextResponse) MarshalTo(b []byte) error {\n\tif len(b) < c.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ReorderingRequired; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDDataI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NSAPI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AltGGSNAddressForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AltGGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AltChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MSInfoChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.BearerControlMode; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EvolvedARPI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedCommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNAMBR; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNBackOffTime; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedCommonFlagsII; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreatePDPContextResponse decodes a given byte sequence as a CreatePDPContextResponse.\nfunc ParseCreatePDPContextResponse(b []byte) (*CreatePDPContextResponse, error) {\n\tc := &CreatePDPContextResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a CreatePDPContextResponse.\nfunc (c *CreatePDPContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.ReorderingRequired:\n\t\t\tc.ReorderingRequired = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.TEIDDataI:\n\t\t\tc.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tc.TEIDCPlane = i\n\t\tcase ie.NSAPI:\n\t\t\tc.NSAPI = i\n\t\tcase ie.ChargingID:\n\t\t\tc.ChargingID = i\n\t\tcase ie.EndUserAddress:\n\t\t\tc.EndUserAddress = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif c.GGSNAddressForCPlane == nil {\n\t\t\t\tc.GGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.GGSNAddressForUserTraffic == nil {\n\t\t\t\tc.GGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.AltGGSNAddressForCPlane == nil {\n\t\t\t\tc.AltGGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AltGGSNAddressForUserTraffic = i\n\t\tcase ie.QoSProfile:\n\t\t\tc.QoSProfile = i\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tif c.ChargingGatewayAddress == nil {\n\t\t\t\tc.ChargingGatewayAddress = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.AltChargingGatewayAddress = i\n\t\tcase ie.CommonFlags:\n\t\t\tc.CommonFlags = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.MSInfoChangeReportingAction:\n\t\t\tc.MSInfoChangeReportingAction = i\n\t\tcase ie.BearerControlMode:\n\t\t\tc.BearerControlMode = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tc.EvolvedARPI = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\tc.ExtendedCommonFlags = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.APNAMBR = i\n\t\tcase ie.GGSNBackOffTime:\n\t\t\tc.GGSNBackOffTime = i\n\t\tcase ie.ExtendedCommonFlagsII:\n\t\t\tc.ExtendedCommonFlagsII = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (c *CreatePDPContextResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ReorderingRequired; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TEIDCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NSAPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EndUserAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AltGGSNAddressForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AltGGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AltChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MSInfoChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.BearerControlMode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EvolvedARPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedCommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNAMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.GGSNBackOffTime; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedCommonFlagsII; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreatePDPContextResponse) SetLength() {\n\tc.Length = uint16(c.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreatePDPContextResponse) MessageTypeName() string {\n\treturn \"Create PDP Context Response\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (c *CreatePDPContextResponse) TEID() uint32 {\n\treturn c.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/create-pdp-context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreatePDPContextResponse into bytes.\n//\n// Deprecated: use CreatePDPContextResponse.Marshal instead.\nfunc (c *CreatePDPContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"CreatePDPContextResponse.Serialize is deprecated. use CreatePDPContextResponse.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreatePDPContextResponse into bytes given as b.\n//\n// Deprecated: use CreatePDPContextResponse.MarshalTo instead.\nfunc (c *CreatePDPContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"CreatePDPContextResponse.SerializeTo is deprecated. use CreatePDPContextResponse.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreatePDPContextResponse decodes bytes as CreatePDPContextResponse.\n//\n// Deprecated: use ParseCreatePDPContextResponse instead.\nfunc DecodeCreatePDPContextResponse(b []byte) (*CreatePDPContextResponse, error) {\n\tlog.Println(\"DecodeCreatePDPContextResponse is deprecated. use ParseCreatePDPContextResponse instead\")\n\treturn ParseCreatePDPContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as CreatePDPContextResponse.\n//\n// Deprecated: use CreatePDPContextResponse.UnmarshalBinary instead.\nfunc (c *CreatePDPContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreatePDPContextResponse.DecodeFromBytes is deprecated. use CreatePDPContextResponse.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreatePDPContextResponse.\n//\n// Deprecated: use CreatePDPContextResponse.MarshalLen instead.\nfunc (c *CreatePDPContextResponse) Len() int {\n\tlog.Println(\"CreatePDPContextResponse.Len is deprecated. use CreatePDPContextResponse.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/create-pdp-context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestCreatePDPContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewCreatePDPContextResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv1.ResCauseRequestAccepted),\n\t\t\t\tie.NewReorderingRequired(false),\n\t\t\t\tie.NewRecovery(0),\n\t\t\t\tie.NewTEIDDataI(0xdeadbeef),\n\t\t\t\tie.NewTEIDCPlane(0xdeadbeef),\n\t\t\t\tie.NewChargingID(1),\n\t\t\t\tie.NewEndUserAddress(\"10.10.10.10\"),\n\t\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x11, 0x00, 0x30, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x80,\n\t\t\t\t// ReorderingRequired\n\t\t\t\t0x08, 0xfe,\n\t\t\t\t// Recovery\n\t\t\t\t0x0e, 0x00,\n\t\t\t\t// TEID-U\n\t\t\t\t0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// TEID-C\n\t\t\t\t0x11, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// ChargingID\n\t\t\t\t0x7f, 0x00, 0x00, 0x00, 0x01,\n\t\t\t\t// End User Address\n\t\t\t\t0x80, 0x00, 0x06, 0xf1, 0x21, 0x0a, 0x0a, 0x0a, 0x0a,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreatePDPContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/delete-pdp-context-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// DeletePDPContextRequest is a DeletePDPContextRequest Header and its IEs above.\ntype DeletePDPContextRequest struct {\n\t*Header\n\tCause               *ie.IE\n\tTeardownInd         *ie.IE\n\tNSAPI               *ie.IE\n\tPCO                 *ie.IE\n\tULI                 *ie.IE\n\tMSTimeZone          *ie.IE\n\tExtendedCommonFlags *ie.IE\n\tULITimestamp        *ie.IE\n\tPrivateExtension    *ie.IE\n\tAdditionalIEs       []*ie.IE\n}\n\n// NewDeletePDPContextRequest creates a new GTPv1 DeletePDPContextRequest.\nfunc NewDeletePDPContextRequest(teid uint32, seq uint16, ies ...*ie.IE) *DeletePDPContextRequest {\n\td := &DeletePDPContextRequest{\n\t\tHeader: NewHeader(0x32, MsgTypeDeletePDPContextRequest, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.TeardownInd:\n\t\t\td.TeardownInd = i\n\t\tcase ie.NSAPI:\n\t\t\td.NSAPI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.MSTimeZone:\n\t\t\td.MSTimeZone = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\td.ExtendedCommonFlags = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal returns the byte sequence generated from a DeletePDPContextRequest.\nfunc (d *DeletePDPContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (d *DeletePDPContextRequest) MarshalTo(b []byte) error {\n\tif len(b) < d.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TeardownInd; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.NSAPI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MSTimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ExtendedCommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeletePDPContextRequest decodes a given byte sequence as a DeletePDPContextRequest.\nfunc ParseDeletePDPContextRequest(b []byte) (*DeletePDPContextRequest, error) {\n\td := &DeletePDPContextRequest{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a DeletePDPContextRequest.\nfunc (d *DeletePDPContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.TeardownInd:\n\t\t\td.TeardownInd = i\n\t\tcase ie.NSAPI:\n\t\t\td.NSAPI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.MSTimeZone:\n\t\t\td.MSTimeZone = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\td.ExtendedCommonFlags = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (d *DeletePDPContextRequest) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TeardownInd; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.NSAPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MSTimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ExtendedCommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeletePDPContextRequest) SetLength() {\n\td.Length = uint16(d.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeletePDPContextRequest) MessageTypeName() string {\n\treturn \"Delete PDP Context Request\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (d *DeletePDPContextRequest) TEID() uint32 {\n\treturn d.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/delete-pdp-context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeletePDPContextRequest into bytes.\n//\n// Deprecated: use DeletePDPContextRequest.Marshal instead.\nfunc (d *DeletePDPContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"DeletePDPContextRequest.Serialize is deprecated. use DeletePDPContextRequest.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeletePDPContextRequest into bytes given as b.\n//\n// Deprecated: use DeletePDPContextRequest.MarshalTo instead.\nfunc (d *DeletePDPContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"DeletePDPContextRequest.SerializeTo is deprecated. use DeletePDPContextRequest.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeletePDPContextRequest decodes bytes as DeletePDPContextRequest.\n//\n// Deprecated: use ParseDeletePDPContextRequest instead.\nfunc DecodeDeletePDPContextRequest(b []byte) (*DeletePDPContextRequest, error) {\n\tlog.Println(\"DecodeDeletePDPContextRequest is deprecated. use ParseDeletePDPContextRequest instead\")\n\treturn ParseDeletePDPContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as DeletePDPContextRequest.\n//\n// Deprecated: use DeletePDPContextRequest.UnmarshalBinary instead.\nfunc (d *DeletePDPContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeletePDPContextRequest.DecodeFromBytes is deprecated. use DeletePDPContextRequest.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeletePDPContextRequest.\n//\n// Deprecated: use DeletePDPContextRequest.MarshalLen instead.\nfunc (d *DeletePDPContextRequest) Len() int {\n\tlog.Println(\"DeletePDPContextRequest.Len is deprecated. use DeletePDPContextRequest.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/delete-pdp-context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestDeletePDPContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeletePDPContextRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv1.ReqCauseNetworkFailure),\n\t\t\t\tie.NewNSAPI(5),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x14, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x08,\n\t\t\t\t// NSAPI\n\t\t\t\t0x14, 0x05,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeletePDPContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/delete-pdp-context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// DeletePDPContextResponse is a DeletePDPContextResponse Header and its IEs above.\ntype DeletePDPContextResponse struct {\n\t*Header\n\tCause            *ie.IE\n\tPCO              *ie.IE\n\tULI              *ie.IE\n\tMSTimeZone       *ie.IE\n\tULITimestamp     *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDeletePDPContextResponse creates a new GTPv1 DeletePDPContextResponse.\nfunc NewDeletePDPContextResponse(teid uint32, seq uint16, ies ...*ie.IE) *DeletePDPContextResponse {\n\td := &DeletePDPContextResponse{\n\t\tHeader: NewHeader(0x32, MsgTypeDeletePDPContextResponse, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.MSTimeZone:\n\t\t\td.MSTimeZone = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal returns the byte sequence generated from a DeletePDPContextResponse.\nfunc (d *DeletePDPContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (d *DeletePDPContextResponse) MarshalTo(b []byte) error {\n\tif len(b) < d.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MSTimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeletePDPContextResponse decodes a given byte sequence as a DeletePDPContextResponse.\nfunc ParseDeletePDPContextResponse(b []byte) (*DeletePDPContextResponse, error) {\n\td := &DeletePDPContextResponse{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a DeletePDPContextResponse.\nfunc (d *DeletePDPContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.MSTimeZone:\n\t\t\td.MSTimeZone = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (d *DeletePDPContextResponse) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MSTimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeletePDPContextResponse) SetLength() {\n\td.Length = uint16(d.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeletePDPContextResponse) MessageTypeName() string {\n\treturn \"Delete PDP Context Response\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (d *DeletePDPContextResponse) TEID() uint32 {\n\treturn d.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/delete-pdp-context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeletePDPContextResponse into bytes.\n//\n// Deprecated: use DeletePDPContextResponse.Marshal instead.\nfunc (d *DeletePDPContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"DeletePDPContextResponse.Serialize is deprecated. use DeletePDPContextResponse.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeletePDPContextResponse into bytes given as b.\n//\n// Deprecated: use DeletePDPContextResponse.MarshalTo instead.\nfunc (d *DeletePDPContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"DeletePDPContextResponse.SerializeTo is deprecated. use DeletePDPContextResponse.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeletePDPContextResponse decodes bytes as DeletePDPContextResponse.\n//\n// Deprecated: use ParseDeletePDPContextResponse instead.\nfunc DecodeDeletePDPContextResponse(b []byte) (*DeletePDPContextResponse, error) {\n\tlog.Println(\"DecodeDeletePDPContextResponse is deprecated. use ParseDeletePDPContextResponse instead\")\n\treturn ParseDeletePDPContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as DeletePDPContextResponse.\n//\n// Deprecated: use DeletePDPContextResponse.UnmarshalBinary instead.\nfunc (d *DeletePDPContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeletePDPContextResponse.DecodeFromBytes is deprecated. use DeletePDPContextResponse.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeletePDPContextResponse.\n//\n// Deprecated: use DeletePDPContextResponse.MarshalLen instead.\nfunc (d *DeletePDPContextResponse) Len() int {\n\tlog.Println(\"DeletePDPContextResponse.Len is deprecated. use DeletePDPContextResponse.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/delete-pdp-context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestDeletePDPContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeletePDPContextResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv1.ResCauseRequestAccepted),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x15, 0x00, 0x06, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeletePDPContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/echo-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// EchoRequest is a EchoRequest Header and its IEs above.\ntype EchoRequest struct {\n\t*Header\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewEchoRequest creates a new GTP.\nfunc NewEchoRequest(seq uint16, ies ...*ie.IE) *EchoRequest {\n\te := &EchoRequest{\n\t\tHeader: NewHeader(0x32, MsgTypeEchoRequest, 0, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EchoRequest.\nfunc (e *EchoRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EchoRequest) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEchoRequest decodes a given byte sequence as a EchoRequest.\nfunc ParseEchoRequest(b []byte) (*EchoRequest, error) {\n\te := &EchoRequest{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a EchoRequest.\nfunc (e *EchoRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ties, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EchoRequest) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EchoRequest) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EchoRequest) MessageTypeName() string {\n\treturn \"Echo Request\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (e *EchoRequest) TEID() uint32 {\n\treturn e.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/echo-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes EchoRequest into bytes.\n//\n// Deprecated: use EchoRequest.Marshal instead.\nfunc (e *EchoRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"EchoRequest.Serialize is deprecated. use EchoRequest.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes EchoRequest into bytes given as b.\n//\n// Deprecated: use EchoRequest.MarshalTo instead.\nfunc (e *EchoRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"EchoRequest.SerializeTo is deprecated. use EchoRequest.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeEchoRequest decodes bytes as EchoRequest.\n//\n// Deprecated: use ParseEchoRequest instead.\nfunc DecodeEchoRequest(b []byte) (*EchoRequest, error) {\n\tlog.Println(\"DecodeEchoRequest is deprecated. use ParseEchoRequest instead\")\n\treturn ParseEchoRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as EchoRequest.\n//\n// Deprecated: use EchoRequest.UnmarshalBinary instead.\nfunc (e *EchoRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"EchoRequest.DecodeFromBytes is deprecated. use EchoRequest.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of EchoRequest.\n//\n// Deprecated: use EchoRequest.MarshalLen instead.\nfunc (e *EchoRequest) Len() int {\n\tlog.Println(\"EchoRequest.Len is deprecated. use EchoRequest.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/echo-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestEchoRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured:  message.NewEchoRequest(0),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x32, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEchoRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/echo-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// EchoResponse is a EchoResponse Header and its IEs above.\ntype EchoResponse struct {\n\t*Header\n\tRecovery         *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewEchoResponse creates a new GTPv1 EchoResponse.\nfunc NewEchoResponse(seq uint16, ies ...*ie.IE) *EchoResponse {\n\te := &EchoResponse{\n\t\tHeader: NewHeader(0x32, MsgTypeEchoResponse, 0, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EchoResponse.\nfunc (e *EchoResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EchoResponse) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEchoResponse decodes a given byte sequence as a EchoResponse.\nfunc ParseEchoResponse(b []byte) (*EchoResponse, error) {\n\te := &EchoResponse{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a EchoResponse.\nfunc (e *EchoResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EchoResponse) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EchoResponse) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EchoResponse) MessageTypeName() string {\n\treturn \"Echo Response\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (e *EchoResponse) TEID() uint32 {\n\treturn e.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/echo-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes EchoResponse into bytes.\n//\n// Deprecated: use EchoResponse.Marshal instead.\nfunc (e *EchoResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"EchoResponse.Serialize is deprecated. use EchoResponse.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes EchoResponse into bytes given as b.\n//\n// Deprecated: use EchoResponse.MarshalTo instead.\nfunc (e *EchoResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"EchoResponse.SerializeTo is deprecated. use EchoResponse.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeEchoResponse decodes bytes as EchoResponse.\n//\n// Deprecated: use ParseEchoResponse instead.\nfunc DecodeEchoResponse(b []byte) (*EchoResponse, error) {\n\tlog.Println(\"DecodeEchoResponse is deprecated. use ParseEchoResponse instead\")\n\treturn ParseEchoResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as EchoResponse.\n//\n// Deprecated: use EchoResponse.UnmarshalBinary instead.\nfunc (e *EchoResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"EchoResponse.DecodeFromBytes is deprecated. use EchoResponse.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of EchoResponse.\n//\n// Deprecated: use EchoResponse.MarshalLen instead.\nfunc (e *EchoResponse) Len() int {\n\tlog.Println(\"EchoResponse.Len is deprecated. use EchoResponse.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/echo-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestEchoResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured:  message.NewEchoResponse(0, ie.NewRecovery(0x80)),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x32, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x0e, 0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEchoResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/end-marker.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// EndMarker is a EndMarker Header and its IEs above.\ntype EndMarker struct {\n\t*Header\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewEndMarker creates a new GTP.\nfunc NewEndMarker(ies ...*ie.IE) *EndMarker {\n\te := &EndMarker{\n\t\tHeader: NewHeader(0x30, MsgTypeEndMarker, 0, 0, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EndMarker.\nfunc (e *EndMarker) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EndMarker) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEndMarker decodes a given byte sequence as a EndMarker.\nfunc ParseEndMarker(b []byte) (*EndMarker, error) {\n\te := &EndMarker{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a EndMarker.\nfunc (e *EndMarker) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ties, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EndMarker) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EndMarker) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EndMarker) MessageTypeName() string {\n\treturn \"End Marker\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (e *EndMarker) TEID() uint32 {\n\treturn e.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/end-marker_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestEndMarker(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured:  message.NewEndMarker(),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x30, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEndMarker(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/error-indication.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\n// ErrorIndication is a ErrorIndication Header and its IEs above.\ntype ErrorIndication struct {\n\t*Header\n\tTEIDDataI        *ie.IE\n\tGTPUPeerAddress  *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewErrorIndication creates a new GTPv1 ErrorIndication.\nfunc NewErrorIndication(teid uint32, seq uint16, ies ...*ie.IE) *ErrorIndication {\n\te := &ErrorIndication{\n\t\tHeader: NewHeader(0x32, MsgTypeErrorIndication, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.TEIDDataI:\n\t\t\te.TEIDDataI = i\n\t\tcase ie.GSNAddress:\n\t\t\te.GTPUPeerAddress = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a ErrorIndication.\nfunc (e *ErrorIndication) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *ErrorIndication) MarshalTo(b []byte) error {\n\tif len(b) < e.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.TEIDDataI; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.GTPUPeerAddress; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseErrorIndication decodes a given byte sequence as a ErrorIndication.\nfunc ParseErrorIndication(b []byte) (*ErrorIndication, error) {\n\te := &ErrorIndication{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a ErrorIndication.\nfunc (e *ErrorIndication) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.TEIDDataI:\n\t\t\te.TEIDDataI = i\n\t\tcase ie.GSNAddress:\n\t\t\te.GTPUPeerAddress = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *ErrorIndication) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.TEIDDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.GTPUPeerAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *ErrorIndication) SetLength() {\n\te.Length = uint16(e.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *ErrorIndication) MessageTypeName() string {\n\treturn \"Errror Indication\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (e *ErrorIndication) TEID() uint32 {\n\treturn e.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/error-indication_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ErrorIndication into bytes.\n//\n// Deprecated: use ErrorIndication.Marshal instead.\nfunc (e *ErrorIndication) Serialize() ([]byte, error) {\n\tlog.Println(\"ErrorIndication.Serialize is deprecated. use ErrorIndication.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes ErrorIndication into bytes given as b.\n//\n// Deprecated: use ErrorIndication.MarshalTo instead.\nfunc (e *ErrorIndication) SerializeTo(b []byte) error {\n\tlog.Println(\"ErrorIndication.SerializeTo is deprecated. use ErrorIndication.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeErrorIndication decodes bytes as ErrorIndication.\n//\n// Deprecated: use ParseErrorIndication instead.\nfunc DecodeErrorIndication(b []byte) (*ErrorIndication, error) {\n\tlog.Println(\"DecodeErrorIndication is deprecated. use ParseErrorIndication instead\")\n\treturn ParseErrorIndication(b)\n}\n\n// DecodeFromBytes decodes bytes as ErrorIndication.\n//\n// Deprecated: use ErrorIndication.UnmarshalBinary instead.\nfunc (e *ErrorIndication) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ErrorIndication.DecodeFromBytes is deprecated. use ErrorIndication.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ErrorIndication.\n//\n// Deprecated: use ErrorIndication.MarshalLen instead.\nfunc (e *ErrorIndication) Len() int {\n\tlog.Println(\"ErrorIndication.Len is deprecated. use ErrorIndication.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/error-indication_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestErrorIndication(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewErrorIndication(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewTEIDDataI(0xdeadbeef),\n\t\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x1a, 0x00, 0x10, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// TEID-U\n\t\t\t\t0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseErrorIndication(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Error definitions.\nvar (\n\tErrInvalidLength      = errors.New(\"got invalid length \")\n\tErrTooShortToMarshal  = errors.New(\"too short to serialize\")\n\tErrTooShortToParse    = errors.New(\"too short to decode as GTPv1\")\n\tErrInvalidMessageType = errors.New(\"got invalid message type\")\n)\n\n// InvalidTypeError indicates the type of an ExtensionHeader is invalid.\ntype InvalidTypeError struct {\n\tType uint8\n}\n\n// Error returns message with the invalid type given.\nfunc (e *InvalidTypeError) Error() string {\n\treturn fmt.Sprintf(\"got invalid type: %v\", e.Type)\n}\n"
  },
  {
    "path": "gtpv1/message/extension-header.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"fmt\"\n\n// ExtensionHeaderType definitions.\nconst (\n\tExtHeaderTypeNoMoreExtensionHeaders                 uint8 = 0b00000000\n\tExtHeaderTypeMBMSSupportIndication                  uint8 = 0b00000001\n\tExtHeaderTypeMSInfoChangeReportingSupportIndication uint8 = 0b00000010\n\tExtHeaderTypeLongPDCPPDUNumber                      uint8 = 0b00000011\n\tExtHeaderTypeServiceClassIndicator                  uint8 = 0b00100000\n\tExtHeaderTypeUDPPort                                uint8 = 0b01000000\n\tExtHeaderTypeRANContainer                           uint8 = 0b10000001\n\tExtHeaderTypeLongPDCPPDUNumberRequired              uint8 = 0b10000010\n\tExtHeaderTypeXwRANContainer                         uint8 = 0b10000011\n\tExtHeaderTypeNRRANContainer                         uint8 = 0b10000100\n\tExtHeaderTypePDUSessionContainer                    uint8 = 0b10000101\n\tExtHeaderTypePDCPPDUNumber                          uint8 = 0b11000000\n\tExtHeaderTypeSuspendRequest                         uint8 = 0b11000001\n\tExtHeaderTypeSuspendResponse                        uint8 = 0b11000010\n)\n\n// ExtensionHeader represents an Extension Header defined in §5.2, TS 29.281 and §6.1 TS 29.060.\ntype ExtensionHeader struct {\n\tType     uint8 // this doesn't exist in the spec, but it's apparently helpful to have\n\tLength   uint8\n\tContent  []byte\n\tNextType uint8\n}\n\n// NewExtensionHeader creates a new ExtensionHeader.\n//\n// ExtensionHeader struct has its own type while it does not actually exist in the packet.\n// Be sure to set an appropriate one - putting a wrong type may cause unexpected errors while\n// using method depends on ExtensionHeader struct.\nfunc NewExtensionHeader(typ uint8, content []byte, nextType uint8) *ExtensionHeader {\n\teh := &ExtensionHeader{\n\t\tType:     typ,\n\t\tContent:  content,\n\t\tNextType: nextType,\n\t}\n\n\teh.SetLength()\n\treturn eh\n}\n\n// Marshal returns the byte sequence generated from an ExtensionHeader.\nfunc (e *ExtensionHeader) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *ExtensionHeader) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < e.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tb[0] = e.Length\n\toffset := int(e.Length)*4 - 1\n\tif l < offset+1 {\n\t\treturn ErrTooShortToMarshal\n\t}\n\tcopy(b[1:offset], e.Content)\n\tb[offset] = e.NextType\n\n\treturn nil\n}\n\n// ParseExtensionHeader decodes given byte sequence as a ExtensionHeader.\nfunc ParseExtensionHeader(b []byte) (*ExtensionHeader, error) {\n\te := &ExtensionHeader{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in ExtensionHeader.\nfunc (e *ExtensionHeader) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\te.Length = b[0]\n\tif e.Length == 0 {\n\t\treturn ErrInvalidLength\n\t}\n\toffset := int(e.Length)*4 - 1\n\tif l < offset+1 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\te.Content = b[1:offset]\n\te.NextType = b[offset]\n\n\treturn nil\n}\n\n// ParseMultiExtensionHeaders parses given bytes sequence as multiple ExtensionHeaders.\nfunc ParseMultiExtensionHeaders(b []byte) ([]*ExtensionHeader, error) {\n\tvar ehs []*ExtensionHeader\n\tnext := ExtHeaderTypeNoMoreExtensionHeaders\n\tfor {\n\t\teh, err := ParseExtensionHeader(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\teh.Type = next\n\n\t\tehs = append(ehs, eh)\n\t\tb = b[eh.MarshalLen():]\n\t\tnext = eh.NextType\n\t\tif next == ExtHeaderTypeNoMoreExtensionHeaders {\n\t\t\tbreak\n\t\t}\n\t\tcontinue\n\t}\n\treturn ehs, nil\n}\n\n// MarshalLen returns the serial length of ExtensionHeader.\nfunc (e *ExtensionHeader) MarshalLen() int {\n\treturn pad4Len(len(e.Content) + 2)\n}\n\n// SetLength sets the length calculated from the length of contents to Length field.\nfunc (e *ExtensionHeader) SetLength() {\n\te.Length = uint8(pad4Len(len(e.Content)+2) / 4)\n}\n\n// String returns an ExtensionHeader fields in human readable format.\nfunc (e *ExtensionHeader) String() string {\n\treturn fmt.Sprintf(\"{Type: %#x, Length: %d, Content: %#x, NextType: %x}\",\n\t\te.Type,\n\t\te.Length,\n\t\te.Content,\n\t\te.NextType,\n\t)\n}\n\n// IsComprehensionRequired reports whether the comprehension of the ExtensionHeader is\n// required or not.\nfunc (e *ExtensionHeader) IsComprehensionRequired() bool {\n\treturn e.Type>>7 == 1\n}\n\nfunc pad4Len(n int) int {\n\treturn n + ((4 - n) & 0b11)\n}\n"
  },
  {
    "path": "gtpv1/message/generic.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// Generic is a Generic Header and its IEs above.\n// This is for handling a non-implemented type of message.\ntype Generic struct {\n\t*Header\n\tIEs []*ie.IE\n}\n\n// NewGeneric creates a new GTPv1 Generic.\nfunc NewGeneric(msgType uint8, teid uint32, seq uint16, ie ...*ie.IE) *Generic {\n\tg := &Generic{\n\t\tHeader: NewHeader(0x32, msgType, teid, seq, nil),\n\t\tIEs:    ie,\n\t}\n\n\tg.SetLength()\n\treturn g\n}\n\n// Marshal returns the byte sequence generated from a Generic.\nfunc (g *Generic) Marshal() ([]byte, error) {\n\tb := make([]byte, g.MarshalLen())\n\tif err := g.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (g *Generic) MarshalTo(b []byte) error {\n\tif g.Header.Payload != nil {\n\t\tg.Header.Payload = nil\n\t}\n\tg.Header.Payload = make([]byte, g.MarshalLen()-g.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range g.IEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(g.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tg.Header.SetLength()\n\treturn g.Header.MarshalTo(b)\n}\n\n// ParseGeneric decodes a given byte sequence as a Generic.\nfunc ParseGeneric(b []byte) (*Generic, error) {\n\tg := &Generic{}\n\tif err := g.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn g, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a Generic.\nfunc (g *Generic) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tg.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(g.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tg.IEs, err = ie.ParseMultiIEs(g.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (g *Generic) MarshalLen() int {\n\tl := g.Header.MarshalLen() - len(g.Header.Payload)\n\n\tfor _, ie := range g.IEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (g *Generic) SetLength() {\n\tg.Header.Length = uint16(g.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (g *Generic) MessageTypeName() string {\n\treturn fmt.Sprintf(\"Unknown (%d)\", g.Type)\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (g *Generic) TEID() uint32 {\n\treturn g.Header.TEID\n}\n\n// AddIE add IEs to Generic type of GTPv2 message and update Length field.\nfunc (g *Generic) AddIE(ie ...*ie.IE) {\n\tg.IEs = append(g.IEs, ie...)\n\tg.SetLength()\n}\n"
  },
  {
    "path": "gtpv1/message/generic_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Generic into bytes.\n//\n// Deprecated: use Generic.Marshal instead.\nfunc (g *Generic) Serialize() ([]byte, error) {\n\tlog.Println(\"Generic.Serialize is deprecated. use Generic.Marshal instead\")\n\treturn g.Marshal()\n}\n\n// SerializeTo serializes Generic into bytes given as b.\n//\n// Deprecated: use Generic.MarshalTo instead.\nfunc (g *Generic) SerializeTo(b []byte) error {\n\tlog.Println(\"Generic.SerializeTo is deprecated. use Generic.MarshalTo instead\")\n\treturn g.MarshalTo(b)\n}\n\n// DecodeGeneric decodes bytes as Generic.\n//\n// Deprecated: use ParseGeneric instead.\nfunc DecodeGeneric(b []byte) (*Generic, error) {\n\tlog.Println(\"DecodeGeneric is deprecated. use ParseGeneric instead\")\n\treturn ParseGeneric(b)\n}\n\n// DecodeFromBytes decodes bytes as Generic.\n//\n// Deprecated: use Generic.UnmarshalBinary instead.\nfunc (g *Generic) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"Generic.DecodeFromBytes is deprecated. use Generic.UnmarshalBinary instead\")\n\treturn g.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of Generic.\n//\n// Deprecated: use Generic.MarshalLen instead.\nfunc (g *Generic) Len() int {\n\tlog.Println(\"Generic.Len is deprecated. use Generic.MarshalLen instead\")\n\treturn g.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/generic_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestGeneric(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured:  message.NewGeneric(message.MsgTypeEchoRequest, 0, 0),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x32, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseGeneric(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/header.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n)\n\n// Header is a GTPv1 common header.\ntype Header struct {\n\tFlags                   uint8\n\tType                    uint8\n\tLength                  uint16\n\tTEID                    uint32\n\tSequenceNumber          uint16\n\tNPDUNumber              uint8\n\tNextExtensionHeaderType uint8\n\tExtensionHeaders        []*ExtensionHeader\n\tPayload                 []byte\n}\n\n// NewHeader creates a new Header.\nfunc NewHeader(flags, mtype uint8, teid uint32, seqnum uint16, payload []byte) *Header {\n\th := &Header{\n\t\tFlags:                   flags,\n\t\tType:                    mtype,\n\t\tTEID:                    teid,\n\t\tSequenceNumber:          seqnum,\n\t\tNextExtensionHeaderType: ExtHeaderTypeNoMoreExtensionHeaders,\n\t\tPayload:                 payload,\n\t}\n\n\th.SetLength()\n\treturn h\n}\n\n// NewHeaderWithNPDUNumber creates a new Header with NPDUNumber.\nfunc NewHeaderWithNPDUNumber(flags, mtype uint8, teid uint32, seqnum uint16, npdu uint8, payload []byte) *Header {\n\th := NewHeader(flags, mtype, teid, seqnum, payload)\n\th.SetNPDUNumber(npdu)\n\treturn h\n}\n\n// NewHeaderWithExtensionHeaders creates a new Header with ExtensionHeaders.\nfunc NewHeaderWithExtensionHeaders(flags, mtype uint8, teid uint32, seqnum uint16, payload []byte, extHdrs ...*ExtensionHeader) *Header {\n\th := NewHeader(flags, mtype, teid, seqnum, payload)\n\t_ = h.AddExtensionHeaders(extHdrs...)\n\treturn h\n}\n\n// NewHeaderFlags returns a Header Flag built by its components given as arguments.\nfunc NewHeaderFlags(v, p, e, s, n int) uint8 {\n\treturn uint8(\n\t\t((v & 0x7) << 5) | ((p & 0x1) << 4) | ((e & 0x1) << 2) | ((s & 0x1) << 1) | (n & 0x1),\n\t)\n}\n\n// Marshal returns the byte sequence generated from a Header.\nfunc (h *Header) Marshal() ([]byte, error) {\n\tb := make([]byte, h.MarshalLen())\n\tif err := h.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (h *Header) MarshalTo(b []byte) error {\n\tif len(b) < h.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tb[0] = h.Flags\n\tb[1] = h.Type\n\tbinary.BigEndian.PutUint16(b[2:4], h.Length)\n\tbinary.BigEndian.PutUint32(b[4:8], h.TEID)\n\n\toffset := 8\n\ts, pn, e := h.HasSequence(), h.HasNPDUNumber(), h.HasExtensionHeader()\n\tif s {\n\t\tbinary.BigEndian.PutUint16(b[offset:offset+2], h.SequenceNumber)\n\t}\n\n\tif pn {\n\t\tb[offset+2] = h.NPDUNumber\n\t}\n\n\tif e {\n\t\tb[offset+3] = h.NextExtensionHeaderType\n\t}\n\n\tif s || pn || e {\n\t\toffset += 4\n\t}\n\n\tif e {\n\t\tfor _, eh := range h.ExtensionHeaders {\n\t\t\tif err := eh.MarshalTo(b[offset:]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\toffset += eh.MarshalLen()\n\t\t}\n\t}\n\n\tcopy(b[offset:], h.Payload)\n\treturn nil\n}\n\n// ParseHeader decodes given byte sequence as a GTPv1 header.\nfunc ParseHeader(b []byte) (*Header, error) {\n\th := &Header{}\n\tif err := h.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn h, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in GTPv1 header.\nfunc (h *Header) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 8 {\n\t\treturn ErrTooShortToParse\n\t}\n\tvar offset = 4\n\th.Flags = b[0]\n\th.Type = b[1]\n\th.Length = binary.BigEndian.Uint16(b[2:4])\n\n\th.TEID = binary.BigEndian.Uint32(b[4:8])\n\toffset += 4\n\n\tif l < int(h.Length)+8 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\ts, pn, e := h.HasSequence(), h.HasNPDUNumber(), h.HasExtensionHeader()\n\t// The optional 4 bytes will append to mandatory GTP header if any one or more S, E flags are set.\n\tif s || pn || e {\n\t\tif h.Length < 4 {\n\t\t\treturn ErrTooShortToParse\n\t\t}\n\t\t// Sequence number must be interpreted only if the S bit is on\n\t\tif s {\n\t\t\th.SequenceNumber = binary.BigEndian.Uint16(b[offset : offset+2])\n\t\t}\n\t\t// NPDUNumber must be interpreted only if the PN bit is on\n\t\tif pn {\n\t\t\th.NPDUNumber = b[offset+2]\n\t\t}\n\t\t// Next Extension Header Type must be interpreted only if the E bit is on.\n\t\tif e {\n\t\t\th.NextExtensionHeaderType = b[offset+3]\n\t\t}\n\t\toffset += 4\n\t}\n\n\tif e {\n\t\tvar err error\n\t\th.ExtensionHeaders, err = ParseMultiExtensionHeaders(b[offset:])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\th.ExtensionHeaders[0].Type = h.NextExtensionHeaderType\n\n\t\tfor _, eh := range h.ExtensionHeaders {\n\t\t\toffset += eh.MarshalLen()\n\t\t}\n\t}\n\n\tif offset > int(h.Length)+8 {\n\t\treturn ErrInvalidLength\n\t}\n\th.Payload = b[offset : 8+h.Length]\n\treturn nil\n}\n\n// SetTEID sets the TEIDFlag to 1 and puts the TEID given into TEID field.\nfunc (h *Header) SetTEID(teid uint32) {\n\th.Flags |= (1 << 3)\n\th.TEID = teid\n}\n\n// Sequence returns SequenceNumber in uint16.\nfunc (h *Header) Sequence() uint16 {\n\treturn h.SequenceNumber\n}\n\n// HasSequence reports whether a Header has SequenceNumber by checking the flag.\nfunc (h *Header) HasSequence() bool {\n\treturn ((int(h.Flags) >> 1) & 0x1) == 1\n}\n\n// SetSequenceNumber sets the SequenceNumber in Header.\nfunc (h *Header) SetSequenceNumber(seq uint16) {\n\th.Flags |= 0x02\n\th.SequenceNumber = seq\n\th.SetLength()\n}\n\n// WithSequenceNumber returns the Header with SequenceNumber added.\nfunc (h *Header) WithSequenceNumber(seq uint16) *Header {\n\th.SetSequenceNumber(seq)\n\treturn h\n}\n\n// HasNPDUNumber reports whether a Header has N-PDU Number by checking the flag.\nfunc (h *Header) HasNPDUNumber() bool {\n\treturn (int(h.Flags) & 0x1) == 1\n}\n\n// SetNPDUNumber sets the NPDUNumber in Header.\nfunc (h *Header) SetNPDUNumber(npdu uint8) {\n\th.Flags |= 0x01\n\th.NPDUNumber = npdu\n\th.SetLength()\n}\n\n// WithNPDUNumber returns the Header with NPDUNumber added.\nfunc (h *Header) WithNPDUNumber(npdu uint8) *Header {\n\th.SetNPDUNumber(npdu)\n\treturn h\n}\n\n// HasExtensionHeader reports whether a Header has extension header by checking the flag.\nfunc (h *Header) HasExtensionHeader() bool {\n\treturn ((int(h.Flags) >> 2) & 0x1) == 1\n}\n\n// SetNextExtensionHeaderType sets the ExtensionHeaderType in Header.\nfunc (h *Header) SetNextExtensionHeaderType(exhType uint8) {\n\th.Flags |= 0x04\n\th.NextExtensionHeaderType = exhType\n}\n\n// WithExtensionHeaders returns the Header with ExtensionHeaders added.\nfunc (h *Header) WithExtensionHeaders(extHdrs ...*ExtensionHeader) *Header {\n\t_ = h.AddExtensionHeaders(extHdrs...)\n\treturn h\n}\n\n// MarshalLen returns the serial length of Header.\nfunc (h *Header) MarshalLen() int {\n\tl := len(h.Payload) + 8\n\tif h.HasSequence() || h.HasNPDUNumber() || h.HasExtensionHeader() {\n\t\tl += 4\n\t}\n\n\tif h.HasExtensionHeader() {\n\t\tfor _, eh := range h.ExtensionHeaders {\n\t\t\tl += eh.MarshalLen()\n\t\t}\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (h *Header) SetLength() {\n\th.Length = uint16(h.MarshalLen() - 8)\n}\n\n// Version returns GTP version in int.\nfunc (h *Header) Version() int {\n\treturn 1\n}\n\n// MessageType returns the type of message.\nfunc (h *Header) MessageType() uint8 {\n\treturn h.Type\n}\n\n// String returns the GTPv1 header values in human readable format.\nfunc (h *Header) String() string {\n\treturn fmt.Sprintf(\n\t\t\"{Flags: %#x, Type: %#x, Length: %d, TEID: %#08x, SequenceNumber: %#04x, NPDUNumber: %#x, \"+\n\t\t\t\"ExtensionHeaderType: %#x, ExtensionHeaders: %v, Payload: %#v}\",\n\t\th.Flags,\n\t\th.Type,\n\t\th.Length,\n\t\th.TEID,\n\t\th.SequenceNumber,\n\t\th.NPDUNumber,\n\t\th.NextExtensionHeaderType,\n\t\th.ExtensionHeaders,\n\t\th.Payload,\n\t)\n}\n\n// AddExtensionHeaders adds ExtensionHeader(s) to Header.\n//\n// This function validates if the next extension header type matches the actual one for safety.\n// To create arbitrary(possibly malformed) Header, access ExtensionHeaders field on your own.\nfunc (h *Header) AddExtensionHeaders(extHdrs ...*ExtensionHeader) error {\n\tif len(extHdrs) < 1 {\n\t\treturn nil\n\t}\n\n\th.Flags |= 0x04\n\n\th.NextExtensionHeaderType = extHdrs[0].Type\n\tnext := h.NextExtensionHeaderType\n\tfor _, eh := range extHdrs {\n\t\tif next != eh.Type {\n\t\t\treturn fmt.Errorf(\"next type: %x does not match the current type: %x\", next, eh.Type)\n\t\t}\n\t\th.ExtensionHeaders = append(h.ExtensionHeaders, eh)\n\t\tnext = eh.NextType\n\t}\n\n\tif next != ExtHeaderTypeNoMoreExtensionHeaders {\n\t\treturn fmt.Errorf(\"non-empty next type: %x is specified but does not exist\", next)\n\t}\n\n\th.SetLength()\n\treturn nil\n}\n"
  },
  {
    "path": "gtpv1/message/header_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Header into bytes.\n//\n// Deprecated: use Header.Marshal instead.\nfunc (h *Header) Serialize() ([]byte, error) {\n\tlog.Println(\"Header.Serialize is deprecated. use Header.Marshal instead\")\n\treturn h.Marshal()\n}\n\n// SerializeTo serializes Header into bytes given as b.\n//\n// Deprecated: use Header.MarshalTo instead.\nfunc (h *Header) SerializeTo(b []byte) error {\n\tlog.Println(\"Header.SerializeTo is deprecated. use Header.MarshalTo instead\")\n\treturn h.MarshalTo(b)\n}\n\n// DecodeHeader decodes bytes as Header.\n//\n// Deprecated: use ParseHeader instead.\nfunc DecodeHeader(b []byte) (*Header, error) {\n\tlog.Println(\"DecodeHeader is deprecated. use ParseHeader instead\")\n\treturn ParseHeader(b)\n}\n\n// DecodeFromBytes decodes bytes as Header.\n//\n// Deprecated: use Header.UnmarshalBinary instead.\nfunc (h *Header) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"Header.DecodeFromBytes is deprecated. use Header.UnmarshalBinary instead\")\n\treturn h.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of Header.\n//\n// Deprecated: use Header.MarshalLen instead.\nfunc (h *Header) Len() int {\n\tlog.Println(\"Header.Len is deprecated. use Header.MarshalLen instead\")\n\treturn h.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/header_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestHeader(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"NoOptionals\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?\n\t\t\t\t\t0, // Sequence Number?\n\t\t\t\t\t0, // N-PDU Number?\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeTPDU, // Message type\n\t\t\t\t0xdeadbeef,          // TEID\n\t\t\t\t0x00,                // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x30, 0xff, 0x00, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"WithSequenceNumber\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?\n\t\t\t\t\t1, // Sequence Number?\n\t\t\t\t\t0, // N-PDU Number?\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeEchoRequest, // Message type\n\t\t\t\t0xdeadbeef,                 // TEID\n\t\t\t\t0xcafe,                     // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x32, 0x01, 0x00, 0x08, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0xca, 0xfe, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"WithNPDUNumber\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?\n\t\t\t\t\t0, // Sequence Number?\n\t\t\t\t\t0, // N-PDU Number?: set to zero at first, set by With... method\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeEchoRequest, // Message type\n\t\t\t\t0xdeadbeef,                 // TEID\n\t\t\t\t0x00,                       // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t).WithNPDUNumber(0xff),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x31, 0x01, 0x00, 0x08, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0x00, 0x00, 0xff, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"WithExtensionHeaders\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?: set to zero at first, set by With... method\n\t\t\t\t\t0, // Sequence Number?\n\t\t\t\t\t0, // N-PDU Number?\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeEchoRequest, // Message type\n\t\t\t\t0xdeadbeef,                 // TEID\n\t\t\t\t0x00,                       // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t).WithExtensionHeaders(\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t\t[]byte{0x22, 0xb8},\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t),\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t\t[]byte{0x22, 0xb8},\n\t\t\t\t\tmessage.ExtHeaderTypeNoMoreExtensionHeaders,\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x34, 0x01, 0x00, 0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0x00, 0x00, 0x00, 0x40, 0x01, 0x22, 0xb8, 0x40,\n\t\t\t\t0x01, 0x22, 0xb8, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"WithSequenceAndNPDUNumber\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?\n\t\t\t\t\t0, // Sequence Number?\n\t\t\t\t\t0, // N-PDU Number?: set to zero at first, set by With... method\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeEchoRequest, // Message type\n\t\t\t\t0xdeadbeef,                 // TEID\n\t\t\t\t0x00,                       // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t).WithSequenceNumber(0xcafe).WithNPDUNumber(0xff),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x33, 0x01, 0x00, 0x08, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0xca, 0xfe, 0xff, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"WithSequenceAndExtensionHeaders\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?: set to zero at first, set by With... method\n\t\t\t\t\t0, // Sequence Number?: set to zero at first, set by With... method\n\t\t\t\t\t0, // N-PDU Number?\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeEchoRequest, // Message type\n\t\t\t\t0xdeadbeef,                 // TEID\n\t\t\t\t0x00,                       // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t).WithSequenceNumber(0xcafe).WithExtensionHeaders(\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t\t[]byte{0x022, 0xb8},\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t),\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t\t[]byte{0x022, 0xb8},\n\t\t\t\t\tmessage.ExtHeaderTypeNoMoreExtensionHeaders,\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x36, 0x01, 0x00, 0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0xca, 0xfe, 0x00, 0x40, 0x01, 0x22, 0xb8, 0x40,\n\t\t\t\t0x01, 0x22, 0xb8, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"WithSequenceAndNPDUAndExtensionHeaders\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(\n\t\t\t\t\t1, // version\n\t\t\t\t\t1, // Protocol Type\n\t\t\t\t\t0, // Next Extension Header?: set to zero at first, set by With... method\n\t\t\t\t\t0, // Sequence Number?: set to zero at first, set by With... method\n\t\t\t\t\t0, // N-PDU Number?: set to zero at first, set by With... method\n\t\t\t\t), // Flags\n\t\t\t\tmessage.MsgTypeEchoRequest, // Message type\n\t\t\t\t0xdeadbeef,                 // TEID\n\t\t\t\t0x00,                       // Sequence Number\n\t\t\t\t[]byte{ // Payload\n\t\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t},\n\t\t\t).WithNPDUNumber(0xff).WithSequenceNumber(0xcafe).WithExtensionHeaders(\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t\t[]byte{0x022, 0xb8},\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t),\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t\t[]byte{0x022, 0xb8},\n\t\t\t\t\tmessage.ExtHeaderTypeNoMoreExtensionHeaders,\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x37, 0x01, 0x00, 0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0xca, 0xfe, 0xff, 0x40, 0x01, 0x22, 0xb8, 0x40,\n\t\t\t\t0x01, 0x22, 0xb8, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseHeader(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn v, nil\n\t})\n}\n\nfunc TestHeaderErrorDetection(t *testing.T) {\n\tcases := []struct {\n\t\tDescription string\n\t\tSerialized  []byte\n\t\tError       error\n\t}{\n\t\t{\n\t\t\tDescription: \"ExtFlagSetButMissingExt\",\n\t\t\tSerialized: []byte{\n\t\t\t\t0b00110110, // Version (3 bits), PT, (*), E, S, PN\n\t\t\t\t0x03,       // Message Type\n\t\t\t\t0x00, 0x04, // Length (2 octets)\n\t\t\t\t0x00, 0x00, 0x00, 0x00, // TEID (4 octets)\n\t\t\t\t0x00, 0x06, // Seqence Number (2 octets)\n\t\t\t\t0xff,       // N-PDU Number (to be ignored)\n\t\t\t\t0b11000001, // Next Extension Header Type\n\t\t\t\t// Extension Header would go here, but is missing\n\t\t\t},\n\t\t\tError: message.ErrTooShortToParse, // Expect too short to parse error, as missing ext header has length 0\n\t\t},\n\t\t{\n\t\t\tDescription: \"IncorrectLength\",\n\t\t\tSerialized: []byte{\n\t\t\t\t0b00110010, // Version (3 bits), PT, (*), E, S, PN\n\t\t\t\t0x03,       // Message Type\n\t\t\t\t0x30, 0x33, // Length (2 octets)\n\t\t\t\t0x00, 0x00, 0x00, 0x00, // TEID (4 octets)\n\t\t\t\t0x00, 0x06, // Seqence Number (2 octets)\n\t\t\t\t0xff,       // N-PDU Number (to be ignored)\n\t\t\t\t0b00000000, // Next Extension Header Type\n\t\t\t},\n\t\t\tError: message.ErrTooShortToParse, // Expect too short to parse error, as missing ext header has length 0\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.Description, func(t *testing.T) {\n\t\t\t_, err := message.ParseHeader(c.Serialized)\n\t\t\tif err != c.Error {\n\t\t\t\tt.Fatalf(\"got '%v' want '%v'\", err, c.Error)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv1/message/message.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n/*\nPackage message provides encoding/decoding feature of GTPv1 protocol.\n*/\npackage message\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// Message Type definitions.\nconst (\n\t_ uint8 = iota\n\tMsgTypeEchoRequest\n\tMsgTypeEchoResponse\n\tMsgTypeVersionNotSupported\n\tMsgTypeNodeAliveRequest\n\tMsgTypeNodeAliveResponse\n\tMsgTypeRedirectionRequest\n\tMsgTypeRedirectionResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tMsgTypeCreatePDPContextRequest // 16\n\tMsgTypeCreatePDPContextResponse\n\tMsgTypeUpdatePDPContextRequest\n\tMsgTypeUpdatePDPContextResponse\n\tMsgTypeDeletePDPContextRequest\n\tMsgTypeDeletePDPContextResponse\n\tMsgTypeCreateAAPDPContextRequest\n\tMsgTypeCreateAAPDPContextResponse\n\tMsgTypeDeleteAAPDPContextRequest\n\tMsgTypeDeleteAAPDPContextResponse\n\tMsgTypeErrorIndication\n\tMsgTypePDUNotificationRequest\n\tMsgTypePDUNotificationResponse\n\tMsgTypePDUNotificationRejectRequest\n\tMsgTypePDUNotificationRejectResponse\n\tMsgTypeSupportedExtensionHeaderNotification\n\tMsgTypeSendRoutingInfoRequest\n\tMsgTypeSendRoutingInfoResponse\n\tMsgTypeFailureReportRequest\n\tMsgTypeFailureReportResponse\n\tMsgTypeNoteMSPresentRequest\n\tMsgTypeNoteMSPresentResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\tMsgTypeIdentificationRequest // 48\n\tMsgTypeIdentificationResponse\n\tMsgTypeSGSNContextRequest\n\tMsgTypeSGSNContextResponse\n\tMsgTypeSGSNContextAcknowledge\n\tMsgTypeDataRecordTransferRequest  uint8 = 240\n\tMsgTypeDataRecordTransferResponse uint8 = 241\n\tMsgTypeEndMarker                  uint8 = 254\n\tMsgTypeTPDU                       uint8 = 255\n)\n\n// Message is an interface that defines Message message.\ntype Message interface {\n\tMarshalTo([]byte) error\n\tUnmarshalBinary(b []byte) error\n\tMarshalLen() int\n\tVersion() int\n\tMessageType() uint8\n\tMessageTypeName() string\n\tTEID() uint32\n\tSetTEID(uint32)\n\tSequence() uint16\n\tSetSequenceNumber(uint16)\n\n\t// deprecated\n\tSerializeTo([]byte) error\n\tDecodeFromBytes(b []byte) error\n}\n\n// Marshal returns the byte sequence generated from a Message instance.\n// Better to use MarshalXxx instead if you know the name of message to be serialized.\nfunc Marshal(g Message) ([]byte, error) {\n\tb := make([]byte, g.MarshalLen())\n\tif err := g.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// Parse parses the given bytes as a Message.\nfunc Parse(b []byte) (Message, error) {\n\tif len(b) < 2 {\n\t\treturn nil, ErrTooShortToParse\n\t}\n\n\tvar m Message\n\n\tswitch b[1] {\n\tcase MsgTypeEchoRequest:\n\t\tm = &EchoRequest{}\n\tcase MsgTypeEchoResponse:\n\t\tm = &EchoResponse{}\n\tcase MsgTypeCreatePDPContextRequest:\n\t\tm = &CreatePDPContextRequest{}\n\tcase MsgTypeCreatePDPContextResponse:\n\t\tm = &CreatePDPContextResponse{}\n\tcase MsgTypeUpdatePDPContextRequest:\n\t\tm = &UpdatePDPContextRequest{}\n\tcase MsgTypeUpdatePDPContextResponse:\n\t\tm = &UpdatePDPContextResponse{}\n\tcase MsgTypeDeletePDPContextRequest:\n\t\tm = &DeletePDPContextRequest{}\n\tcase MsgTypeVersionNotSupported:\n\t\tm = &VersionNotSupported{}\n\tcase MsgTypeDeletePDPContextResponse:\n\t\tm = &DeletePDPContextResponse{}\n\t/* TODO: Implement!\n\tcase MsgTypeNodeAliveRequest:\n\t\tm = &NodeAliveReq{}\n\tcase MsgTypeNodeAliveResponse:\n\t\tm = &NodeAliveRes{}\n\tcase MsgTypeRedirectionRequest:\n\t\tm = &RedirectionReq{}\n\tcase MsgTypeRedirectionResponse:\n\t\tm = &RedirectionRes{}\n\tcase MsgTypeCreateAaPDPContextRequest:\n\t\tm = &CreateAaPDPContextReq{}\n\tcase MsgTypeCreateAaPDPContextResponse:\n\t\tm = &CreateAaPDPContextRes{}\n\tcase MsgTypeDeleteAaPDPContextRequest:\n\t\tm = &DeleteAaPDPContextReq{}\n\tcase MsgTypeDeleteAaPDPContextResponse:\n\t\tm = &DeleteAaPDPContextRes{}\n\t*/\n\tcase MsgTypeErrorIndication:\n\t\tm = &ErrorIndication{}\n\t/* TODO: Implement!\n\tcase MsgTypePduNotificationRequest:\n\t\tm = &PduNotificationReq{}\n\tcase MsgTypePduNotificationResponse:\n\t\tm = &PduNotificationRes{}\n\tcase MsgTypePduNotificationRejectRequest:\n\t\tm = &PduNotificationRejectReq{}\n\tcase MsgTypePduNotificationRejectResponse:\n\t\tm = &PduNotificationRejectRes{}\n\t*/\n\tcase MsgTypeSupportedExtensionHeaderNotification:\n\t\tm = &SupportedExtensionHeaderNotification{}\n\t/* TODO: Implement!\n\tcase MsgTypeSendRoutingInfoRequest:\n\t\tm = &SendRoutingInfoReq{}\n\tcase MsgTypeSendRoutingInfoResponse:\n\t\tm = &SendRoutingInfoRes{}\n\tcase MsgTypeFailureReportRequest:\n\t\tm = &FailureReportReq{}\n\tcase MsgTypeFailureReportResponse:\n\t\tm = &FailureReportRes{}\n\tcase MsgTypeNoteMsPresentRequest:\n\t\tm = &NoteMsPresentReq{}\n\tcase MsgTypeNoteMsPresentResponse:\n\t\tm = &NoteMsPresentRes{}\n\tcase MsgTypeIdentificationRequest:\n\t\tm = &IdentificationReq{}\n\tcase MsgTypeIdentificationResponse:\n\t\tm = &IdentificationRes{}\n\tcase MsgTypeSgsnContextRequest:\n\t\tm = &SgsnContextReq{}\n\tcase MsgTypeSgsnContextResponse:\n\t\tm = &SgsnContextRes{}\n\tcase MsgTypeSgsnContextAcknowledge:\n\t\tm = &SgsnContextAck{}\n\tcase MsgTypeDataRecordTransferRequest:\n\t\tm = &DataRecordTransferReq{}\n\tcase MsgTypeDataRecordTransferResponse:\n\t\tm = &DataRecordTransferRes{}\n\t*/\n\tcase MsgTypeEndMarker:\n\t\tm = &EndMarker{}\n\tcase MsgTypeTPDU:\n\t\tm = &TPDU{}\n\tdefault:\n\t\tm = &Generic{}\n\t}\n\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// Prettify returns a Message in prettified representation in string.\n//\n// Note that this relies much on reflect package, and thus the frequent use of\n// this function may have a serious impact on the performance of your software.\nfunc Prettify(m Message) string {\n\tname := m.MessageTypeName()\n\theader := strings.TrimSuffix(fmt.Sprint(m), \"}\")\n\n\tv := reflect.Indirect(reflect.ValueOf(m))\n\tn := v.NumField() - 1\n\tfields := make([]*field, n)\n\tfor i := 1; i < n+1; i++ { // Skip *Header\n\t\tfields[i-1] = &field{name: v.Type().Field(i).Name, maybeIE: v.Field(i).Interface()}\n\t}\n\n\treturn fmt.Sprintf(\"{%s: %s, IEs: [%v]}\", name, header, strings.Join(prettifyFields(fields), \", \"))\n}\n\ntype field struct {\n\tname    string\n\tmaybeIE interface{}\n}\n\nfunc prettifyFields(fields []*field) []string {\n\tret := []string{}\n\tfor _, field := range fields {\n\t\tif field.maybeIE == nil {\n\t\t\tret = append(ret, prettifyIE(field.name, nil))\n\t\t\tcontinue\n\t\t}\n\n\t\t// TODO: do this recursively?\n\t\tv, ok := field.maybeIE.(*ie.IE)\n\t\tif !ok {\n\t\t\t// only for AdditionalIEs field\n\t\t\tif ies, ok := field.maybeIE.([]*ie.IE); ok {\n\t\t\t\tvals := make([]string, len(ies))\n\t\t\t\tfor i, val := range ies {\n\t\t\t\t\tvals[i] = fmt.Sprint(val)\n\t\t\t\t}\n\t\t\t\tret = append(ret, fmt.Sprintf(\"{%s: [%v]}\", field.name, strings.Join(vals, \", \")))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tret = append(ret, prettifyIE(field.name, v))\n\t}\n\n\treturn ret\n}\n\nfunc prettifyIE(name string, i *ie.IE) string {\n\treturn fmt.Sprintf(\"{%s: %v}\", name, i)\n}\n"
  },
  {
    "path": "gtpv1/message/message_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Message into bytes.\n//\n// Deprecated: use Marshal instead.\nfunc Serialize(m Message) ([]byte, error) {\n\tlog.Println(\"Serialize is deprecated. use Marshal instead\")\n\treturn Marshal(m)\n}\n\n// Decode decodes bytes as Message.\n//\n// Deprecated: use Parse instead.\nfunc Decode(b []byte) (Message, error) {\n\tlog.Println(\"Decode is deprecated. use Parse instead\")\n\treturn Parse(b)\n}\n"
  },
  {
    "path": "gtpv1/message/message_fuzz_test.go",
    "content": "package message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := message.Parse(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n\nfunc FuzzHeaderParse(f *testing.F) {\n\tf.Add([]byte(\"10000000\"))\n\tf.Add([]byte(\"70\\x00\\x0400000000\\x000\"))\n\tf.Add([]byte(\"70\\x00\\x0400000000\\x0100\\x00\"))\n\n\tf.Fuzz(func(t *testing.T, pkt []byte) {\n\t\theader, err := message.ParseHeader(pkt)\n\t\tif header == nil && err == nil {\n\t\t\tt.Errorf(\"nil without error\")\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/supported-extension-header-notification.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// SupportedExtensionHeaderNotification is a SupportedExtensionHeaderNotification Header and its IEs above.\ntype SupportedExtensionHeaderNotification struct {\n\t*Header\n\tExtensionHeaderTypeList *ie.IE\n\tAdditionalIEs           []*ie.IE\n}\n\n// NewSupportedExtensionHeaderNotification creates a new GTPv1 SupportedExtensionHeaderNotification.\nfunc NewSupportedExtensionHeaderNotification(teid uint32, seq uint16, ies ...*ie.IE) *SupportedExtensionHeaderNotification {\n\te := &SupportedExtensionHeaderNotification{\n\t\tHeader: NewHeader(0x30, MsgTypeSupportedExtensionHeaderNotification, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.ExtensionHeaderTypeList:\n\t\t\te.ExtensionHeaderTypeList = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a SupportedExtensionHeaderNotification.\nfunc (e *SupportedExtensionHeaderNotification) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *SupportedExtensionHeaderNotification) MarshalTo(b []byte) error {\n\tif len(b) < e.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.ExtensionHeaderTypeList; ie != nil {\n\t\tif err := ie.MarshalTo(e.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseSupportedExtensionHeaderNotification decodes a given byte sequence as a SupportedExtensionHeaderNotification.\nfunc ParseSupportedExtensionHeaderNotification(b []byte) (*SupportedExtensionHeaderNotification, error) {\n\te := &SupportedExtensionHeaderNotification{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a SupportedExtensionHeaderNotification.\nfunc (e *SupportedExtensionHeaderNotification) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.ExtensionHeaderTypeList:\n\t\t\te.ExtensionHeaderTypeList = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *SupportedExtensionHeaderNotification) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.ExtensionHeaderTypeList; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *SupportedExtensionHeaderNotification) SetLength() {\n\te.Length = uint16(e.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *SupportedExtensionHeaderNotification) MessageTypeName() string {\n\treturn \"Supported Extension Header Notification\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (e *SupportedExtensionHeaderNotification) TEID() uint32 {\n\treturn e.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/supported-extension-header-notification_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestSupportedExtensionHeaderNotification(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewSupportedExtensionHeaderNotification(\n\t\t\t\ttestutils.TestBearerInfo.TEID, 0,\n\t\t\t\tie.NewExtensionHeaderTypeList(\n\t\t\t\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t\t\t\t\tmessage.ExtHeaderTypeUDPPort,\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x30, 0x1f, 0x00, 0x04, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t// ExtensionHeaderTypeList\n\t\t\t\t0x8d, 0x02, 0x85, 0x40,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseSupportedExtensionHeaderNotification(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/t-pdu.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\n// TPDU is a TPDU.\ntype TPDU struct {\n\t*Header\n}\n\n// NewTPDU creates a new T-PDU message.\nfunc NewTPDU(teid uint32, payload []byte) *TPDU {\n\tt := &TPDU{Header: NewHeader(0x30, MsgTypeTPDU, teid, 0, payload)}\n\n\tt.SetLength()\n\treturn t\n}\n\n// NewTPDUWithSequence creates a new T-PDU message with the given Sequence Number.\nfunc NewTPDUWithSequence(teid uint32, seq uint16, payload []byte) *TPDU {\n\tt := &TPDU{Header: NewHeader(0x32, MsgTypeTPDU, teid, seq, payload)}\n\n\tt.SetLength()\n\treturn t\n}\n\n// NewTPDUWithExtentionHeader creates a new T-PDU message with the given Extension Headers.\nfunc NewTPDUWithExtentionHeader(teid uint32, payload []byte, extHdrs ...*ExtensionHeader) *TPDU {\n\tt := &TPDU{Header: NewHeaderWithExtensionHeaders(0x34, MsgTypeTPDU, teid, 0, payload, extHdrs...)}\n\n\tt.SetLength()\n\treturn t\n}\n\n// Marshal returns the byte sequence generated from a TPDU.\nfunc (t *TPDU) Marshal() ([]byte, error) {\n\tb := make([]byte, t.MarshalLen())\n\tif err := t.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (t *TPDU) MarshalTo(b []byte) error {\n\tif len(b) < t.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\n\tt.Header.SetLength()\n\treturn t.Header.MarshalTo(b)\n}\n\n// ParseTPDU decodes a given byte sequence as a TPDU.\nfunc ParseTPDU(b []byte) (*TPDU, error) {\n\tt := &TPDU{}\n\tif err := t.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn t, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a TPDU.\nfunc (t *TPDU) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tt.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (t *TPDU) MarshalLen() int {\n\treturn t.Header.MarshalLen()\n}\n\n// SetLength sets the length in Length field.\nfunc (t *TPDU) SetLength() {\n\tt.Header.SetLength()\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (t *TPDU) MessageTypeName() string {\n\treturn \"T-PDU\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (t *TPDU) TEID() uint32 {\n\treturn t.Header.TEID\n}\n\n// Decapsulate returns payload as raw []byte.\nfunc (t *TPDU) Decapsulate() []byte {\n\treturn t.Header.Payload\n}\n"
  },
  {
    "path": "gtpv1/message/t-pdu_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes TPDU into bytes.\n//\n// Deprecated: use TPDU.Marshal instead.\nfunc (t *TPDU) Serialize() ([]byte, error) {\n\tlog.Println(\"TPDU.Serialize is deprecated. use TPDU.Marshal instead\")\n\treturn t.Marshal()\n}\n\n// SerializeTo serializes TPDU into bytes given as b.\n//\n// Deprecated: use TPDU.MarshalTo instead.\nfunc (t *TPDU) SerializeTo(b []byte) error {\n\tlog.Println(\"TPDU.SerializeTo is deprecated. use TPDU.MarshalTo instead\")\n\treturn t.MarshalTo(b)\n}\n\n// DecodeTPDU decodes bytes as TPDU.\n//\n// Deprecated: use ParseTPDU instead.\nfunc DecodeTPDU(b []byte) (*TPDU, error) {\n\tlog.Println(\"DecodeTPDU is deprecated. use ParseTPDU instead\")\n\treturn ParseTPDU(b)\n}\n\n// DecodeFromBytes decodes bytes as TPDU.\n//\n// Deprecated: use TPDU.UnmarshalBinary instead.\nfunc (t *TPDU) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"TPDU.DecodeFromBytes is deprecated. use TPDU.UnmarshalBinary instead\")\n\treturn t.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of TPDU.\n//\n// Deprecated: use TPDU.MarshalLen instead.\nfunc (t *TPDU) Len() int {\n\tlog.Println(\"TPDU.Len is deprecated. use TPDU.MarshalLen instead\")\n\treturn t.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/t-pdu_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestTPDU(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured:  message.NewTPDU(0xdeadbeef, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x30, 0xff, 0x00, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"With-Sequence\",\n\t\t\tStructured:  message.NewTPDUWithSequence(0xdeadbeef, 0x0001, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x32, 0xff, 0x00, 0x08, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0x00, 0x01, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"With-ExtensionHeader\",\n\t\t\tStructured: message.NewTPDUWithExtentionHeader(\n\t\t\t\t0xdeadbeef,\n\t\t\t\t[]byte{0xde, 0xad, 0xbe, 0xef},\n\t\t\t\tmessage.NewExtensionHeader(\n\t\t\t\t\tmessage.ExtHeaderTypePDUSessionContainer,\n\t\t\t\t\t[]byte{0x00, 0x05},\n\t\t\t\t\tmessage.ExtHeaderTypeNoMoreExtensionHeaders,\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x34, 0xff, 0x00, 0x0c, 0xde, 0xad, 0xbe,\n\t\t\t\t0xef, 0x00, 0x00, 0x00,\n\t\t\t\t// Next extension header type\n\t\t\t\t0x85,\n\t\t\t\t// Extension Header\n\t\t\t\t0x01, 0x00, 0x05, 0x00,\n\t\t\t\t// Payload\n\t\t\t\t0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseTPDU(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/update-pdp-context-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserveu.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// UpdatePDPContextRequest is a UpdatePDPContextRequest Header and its IEs above.\ntype UpdatePDPContextRequest struct {\n\t*Header\n\tIMSI                                 *ie.IE\n\tRAI                                  *ie.IE\n\tRecovery                             *ie.IE\n\tTEIDDataI                            *ie.IE\n\tTEIDCPlane                           *ie.IE\n\tNSAPI                                *ie.IE\n\tTraceReference                       *ie.IE\n\tTraceType                            *ie.IE\n\tPCO                                  *ie.IE\n\tSGSNAddressForCPlane                 *ie.IE\n\tSGSNAddressForUserTraffic            *ie.IE\n\tAlternativeSGSNAddressForCPlane      *ie.IE\n\tAlternativeSGSNAddressForUserTraffic *ie.IE\n\tQoSProfile                           *ie.IE\n\tTFT                                  *ie.IE\n\tTriggerID                            *ie.IE\n\tOMCIdentity                          *ie.IE\n\tCommonFlags                          *ie.IE\n\tRATType                              *ie.IE\n\tULI                                  *ie.IE\n\tMSTimeZone                           *ie.IE\n\tAdditionalTraceInfo                  *ie.IE\n\tDirectTunnelFlags                    *ie.IE\n\tEvolvedARPI                          *ie.IE\n\tExtendedCommonFlags                  *ie.IE\n\tUCI                                  *ie.IE\n\tAPNAMBR                              *ie.IE\n\tSignallingPriorityIndication         *ie.IE\n\tCNOperatorSelectionEntity            *ie.IE\n\tIMEI                                 *ie.IE\n\tPrivateExtension                     *ie.IE\n\tAdditionalIEs                        []*ie.IE\n}\n\n// NewUpdatePDPContextRequest creates a new GTPv1 UpdatePDPContextRequest.\nfunc NewUpdatePDPContextRequest(teid uint32, seq uint16, ies ...*ie.IE) *UpdatePDPContextRequest {\n\tu := &UpdatePDPContextRequest{\n\t\tHeader: NewHeader(0x32, MsgTypeUpdatePDPContextRequest, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tu.IMSI = i\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tu.RAI = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.TEIDDataI:\n\t\t\tu.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tu.TEIDCPlane = i\n\t\tcase ie.NSAPI:\n\t\t\tu.NSAPI = i\n\t\tcase ie.TraceReference:\n\t\t\tu.TraceReference = i\n\t\tcase ie.TraceType:\n\t\t\tu.TraceType = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tu.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.SGSNAddressForCPlane == nil {\n\t\t\t\tu.SGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.SGSNAddressForUserTraffic == nil {\n\t\t\t\tu.SGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.AlternativeSGSNAddressForCPlane == nil {\n\t\t\t\tu.AlternativeSGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tu.AlternativeSGSNAddressForUserTraffic = i\n\t\tcase ie.QoSProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.TrafficFlowTemplate:\n\t\t\tu.TFT = i\n\t\tcase ie.TriggerID:\n\t\t\tu.TriggerID = i\n\t\tcase ie.OMCIdentity:\n\t\t\tu.OMCIdentity = i\n\t\tcase ie.CommonFlags:\n\t\t\tu.CommonFlags = i\n\t\tcase ie.RATType:\n\t\t\tu.RATType = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tu.ULI = i\n\t\tcase ie.MSTimeZone:\n\t\t\tu.MSTimeZone = i\n\t\tcase ie.AdditionalTraceInfo:\n\t\t\tu.AdditionalTraceInfo = i\n\t\tcase ie.DirectTunnelFlags:\n\t\t\tu.DirectTunnelFlags = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tu.EvolvedARPI = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\tu.ExtendedCommonFlags = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tu.UCI = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tu.APNAMBR = i\n\t\tcase ie.SignallingPriorityIndication:\n\t\t\tu.SignallingPriorityIndication = i\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tu.CNOperatorSelectionEntity = i\n\t\tcase ie.IMEISV:\n\t\t\tu.IMEI = i\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tu.SetLength()\n\treturn u\n}\n\n// Marshal returns the byte sequence generated from a UpdatePDPContextRequest.\nfunc (u *UpdatePDPContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, u.MarshalLen())\n\tif err := u.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (u *UpdatePDPContextRequest) MarshalTo(b []byte) error {\n\tif len(b) < u.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\tu.Header.Payload = make([]byte, u.MarshalLen()-u.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := u.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.RAI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDDataI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.NSAPI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TraceReference; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TraceType; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.AlternativeSGSNAddressForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.AlternativeSGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TFT; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TriggerID; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.OMCIdentity; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.CommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.MSTimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.AdditionalTraceInfo; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.DirectTunnelFlags; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.EvolvedARPI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.ExtendedCommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.UCI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.APNAMBR; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.SignallingPriorityIndication; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.CNOperatorSelectionEntity; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.IMEI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(u.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tu.Header.SetLength()\n\treturn u.Header.MarshalTo(b)\n}\n\n// ParseUpdatePDPContextRequest decodes a given byte sequence as a UpdatePDPContextRequest.\nfunc ParseUpdatePDPContextRequest(b []byte) (*UpdatePDPContextRequest, error) {\n\tu := &UpdatePDPContextRequest{}\n\tif err := u.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn u, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a UpdatePDPContextRequest.\nfunc (u *UpdatePDPContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tu.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(u.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(u.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tu.IMSI = i\n\t\tcase ie.RouteingAreaIdentity:\n\t\t\tu.RAI = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.TEIDDataI:\n\t\t\tu.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tu.TEIDCPlane = i\n\t\tcase ie.NSAPI:\n\t\t\tu.NSAPI = i\n\t\tcase ie.TraceReference:\n\t\t\tu.TraceReference = i\n\t\tcase ie.TraceType:\n\t\t\tu.TraceType = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tu.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.SGSNAddressForCPlane == nil {\n\t\t\t\tu.SGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.SGSNAddressForUserTraffic == nil {\n\t\t\t\tu.SGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.AlternativeSGSNAddressForCPlane == nil {\n\t\t\t\tu.AlternativeSGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tu.AlternativeSGSNAddressForUserTraffic = i\n\t\tcase ie.QoSProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.TrafficFlowTemplate:\n\t\t\tu.TFT = i\n\t\tcase ie.TriggerID:\n\t\t\tu.TriggerID = i\n\t\tcase ie.OMCIdentity:\n\t\t\tu.OMCIdentity = i\n\t\tcase ie.CommonFlags:\n\t\t\tu.CommonFlags = i\n\t\tcase ie.RATType:\n\t\t\tu.RATType = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tu.ULI = i\n\t\tcase ie.MSTimeZone:\n\t\t\tu.MSTimeZone = i\n\t\tcase ie.AdditionalTraceInfo:\n\t\t\tu.AdditionalTraceInfo = i\n\t\tcase ie.DirectTunnelFlags:\n\t\t\tu.DirectTunnelFlags = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tu.EvolvedARPI = i\n\t\tcase ie.ExtendedCommonFlags:\n\t\t\tu.ExtendedCommonFlags = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tu.UCI = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tu.APNAMBR = i\n\t\tcase ie.SignallingPriorityIndication:\n\t\t\tu.SignallingPriorityIndication = i\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tu.CNOperatorSelectionEntity = i\n\t\tcase ie.IMEISV:\n\t\t\tu.IMEI = i\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (u *UpdatePDPContextRequest) MarshalLen() int {\n\tl := u.Header.MarshalLen() - len(u.Header.Payload)\n\n\tif ie := u.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.RAI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.NSAPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TraceReference; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TraceType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.SGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.AlternativeSGSNAddressForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.AlternativeSGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TFT; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TriggerID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.OMCIdentity; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.CommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.MSTimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.AdditionalTraceInfo; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.DirectTunnelFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.EvolvedARPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.ExtendedCommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.UCI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.APNAMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.SignallingPriorityIndication; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.CNOperatorSelectionEntity; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.IMEI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (u *UpdatePDPContextRequest) SetLength() {\n\tu.Length = uint16(u.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (u *UpdatePDPContextRequest) MessageTypeName() string {\n\treturn \"Update PDP Context Request\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (u *UpdatePDPContextRequest) TEID() uint32 {\n\treturn u.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/update-pdp-context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes UpdatePDPContextRequest into bytes.\n//\n// Deprecated: use UpdatePDPContextRequest.Marshal instead.\nfunc (u *UpdatePDPContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"UpdatePDPContextRequest.Serialize is deprecated. use UpdatePDPContextRequest.Marshal instead\")\n\treturn u.Marshal()\n}\n\n// SerializeTo serializes UpdatePDPContextRequest into bytes given as b.\n//\n// Deprecated: use UpdatePDPContextRequest.MarshalTo instead.\nfunc (u *UpdatePDPContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"UpdatePDPContextRequest.SerializeTo is deprecated. use UpdatePDPContextRequest.MarshalTo instead\")\n\treturn u.MarshalTo(b)\n}\n\n// DecodeUpdatePDPContextRequest decodes bytes as UpdatePDPContextRequest.\n//\n// Deprecated: use ParseUpdatePDPContextRequest instead.\nfunc DecodeUpdatePDPContextRequest(b []byte) (*UpdatePDPContextRequest, error) {\n\tlog.Println(\"DecodeUpdatePDPContextRequest is deprecated. use ParseUpdatePDPContextRequest instead\")\n\treturn ParseUpdatePDPContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as UpdatePDPContextRequest.\n//\n// Deprecated: use UpdatePDPContextRequest.UnmarshalBinary instead.\nfunc (u *UpdatePDPContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"UpdatePDPContextRequest.DecodeFromBytes is deprecated. use UpdatePDPContextRequest.UnmarshalBinary instead\")\n\treturn u.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of UpdatePDPContextRequest.\n//\n// Deprecated: use UpdatePDPContextRequest.MarshalLen instead.\nfunc (u *UpdatePDPContextRequest) Len() int {\n\tlog.Println(\"UpdatePDPContextRequest.Len is deprecated. use UpdatePDPContextRequest.MarshalLen instead\")\n\treturn u.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/update-pdp-context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestUpdatePDPContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewUpdatePDPContextRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123450123456789\"),\n\t\t\t\tie.NewTEIDDataI(0xdeadbeef),\n\t\t\t\tie.NewTEIDCPlane(0xdeadbeef),\n\t\t\t\tie.NewNSAPI(5),\n\t\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x12, 0x00, 0x27, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x02, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9,\n\t\t\t\t// TEID-U\n\t\t\t\t0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// TEID-C\n\t\t\t\t0x11, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// NSAPI\n\t\t\t\t0x14, 0x05,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdatePDPContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/update-pdp-context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserveu.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// UpdatePDPContextResponse is a UpdatePDPContextResponse Header and its IEs above.\ntype UpdatePDPContextResponse struct {\n\t*Header\n\tCause                         *ie.IE\n\tRecovery                      *ie.IE\n\tTEIDDataI                     *ie.IE\n\tTEIDCPlane                    *ie.IE\n\tChargingID                    *ie.IE\n\tPCO                           *ie.IE\n\tGGSNAddressForCPlane          *ie.IE\n\tGGSNAddressForUserTraffic     *ie.IE\n\tAltGGSNAddressForCPlane       *ie.IE\n\tAltGGSNAddressForUserTraffic  *ie.IE\n\tQoSProfile                    *ie.IE\n\tChargingGatewayAddress        *ie.IE\n\tAltChargingGatewayAddress     *ie.IE\n\tCommonFlags                   *ie.IE\n\tAPNRestriction                *ie.IE\n\tBearerControlMode             *ie.IE\n\tMSInfoChangeReportingAction   *ie.IE\n\tEvolvedARPI                   *ie.IE\n\tCSGInformationReportingAction *ie.IE\n\tAPNAMBR                       *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewUpdatePDPContextResponse creates a new GTPv1 UpdatePDPContextResponse.\nfunc NewUpdatePDPContextResponse(teid uint32, seq uint16, ies ...*ie.IE) *UpdatePDPContextResponse {\n\tu := &UpdatePDPContextResponse{\n\t\tHeader: NewHeader(0x32, MsgTypeUpdatePDPContextResponse, teid, seq, nil),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tu.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.TEIDDataI:\n\t\t\tu.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tu.TEIDCPlane = i\n\t\tcase ie.ChargingID:\n\t\t\tu.ChargingID = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tu.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.GGSNAddressForCPlane == nil {\n\t\t\t\tu.GGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.GGSNAddressForUserTraffic == nil {\n\t\t\t\tu.GGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.AltGGSNAddressForCPlane == nil {\n\t\t\t\tu.AltGGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tu.AltGGSNAddressForUserTraffic = i\n\t\tcase ie.QoSProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tif u.ChargingGatewayAddress == nil {\n\t\t\t\tu.ChargingGatewayAddress = i\n\t\t\t} else if u.AltChargingGatewayAddress == nil {\n\t\t\t\tu.AltChargingGatewayAddress = i\n\t\t\t}\n\t\tcase ie.CommonFlags:\n\t\t\tu.CommonFlags = i\n\t\tcase ie.APNRestriction:\n\t\t\tu.APNRestriction = i\n\t\tcase ie.BearerControlMode:\n\t\t\tu.BearerControlMode = i\n\t\tcase ie.MSInfoChangeReportingAction:\n\t\t\tu.MSInfoChangeReportingAction = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tu.EvolvedARPI = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tu.CSGInformationReportingAction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tu.APNAMBR = i\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tu.SetLength()\n\treturn u\n}\n\n// Marshal returns the byte sequence generated from a UpdatePDPContextResponse.\nfunc (u *UpdatePDPContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, u.MarshalLen())\n\tif err := u.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (u *UpdatePDPContextResponse) MarshalTo(b []byte) error {\n\tif len(b) < u.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\tu.Header.Payload = make([]byte, u.MarshalLen()-u.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := u.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDDataI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingID; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.AltGGSNAddressForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.AltGGSNAddressForUserTraffic; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.AltChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.CommonFlags; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.APNRestriction; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.BearerControlMode; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.MSInfoChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.EvolvedARPI; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.APNAMBR; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(u.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(u.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tu.Header.SetLength()\n\treturn u.Header.MarshalTo(b)\n}\n\n// ParseUpdatePDPContextResponse decodes a given byte sequence as a UpdatePDPContextResponse.\nfunc ParseUpdatePDPContextResponse(b []byte) (*UpdatePDPContextResponse, error) {\n\tu := &UpdatePDPContextResponse{}\n\tif err := u.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn u, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a UpdatePDPContextResponse.\nfunc (u *UpdatePDPContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tu.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(u.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\ties, err := ie.ParseMultiIEs(u.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tu.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tu.Recovery = i\n\t\tcase ie.TEIDDataI:\n\t\t\tu.TEIDDataI = i\n\t\tcase ie.TEIDCPlane:\n\t\t\tu.TEIDCPlane = i\n\t\tcase ie.ChargingID:\n\t\t\tu.ChargingID = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tu.PCO = i\n\t\tcase ie.GSNAddress:\n\t\t\tif u.GGSNAddressForCPlane == nil {\n\t\t\t\tu.GGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.GGSNAddressForUserTraffic == nil {\n\t\t\t\tu.GGSNAddressForUserTraffic = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.AltGGSNAddressForCPlane == nil {\n\t\t\t\tu.AltGGSNAddressForCPlane = i\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tu.AltGGSNAddressForUserTraffic = i\n\t\tcase ie.QoSProfile:\n\t\t\tu.QoSProfile = i\n\t\tcase ie.ChargingGatewayAddress:\n\t\t\tif u.ChargingGatewayAddress == nil {\n\t\t\t\tu.ChargingGatewayAddress = i\n\t\t\t} else if u.AltChargingGatewayAddress == nil {\n\t\t\t\tu.AltChargingGatewayAddress = i\n\t\t\t}\n\t\tcase ie.CommonFlags:\n\t\t\tu.CommonFlags = i\n\t\tcase ie.APNRestriction:\n\t\t\tu.APNRestriction = i\n\t\tcase ie.BearerControlMode:\n\t\t\tu.BearerControlMode = i\n\t\tcase ie.MSInfoChangeReportingAction:\n\t\t\tu.MSInfoChangeReportingAction = i\n\t\tcase ie.EvolvedAllocationRetentionPriorityI:\n\t\t\tu.EvolvedARPI = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tu.CSGInformationReportingAction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tu.APNAMBR = i\n\t\tcase ie.PrivateExtension:\n\t\t\tu.PrivateExtension = i\n\t\tdefault:\n\t\t\tu.AdditionalIEs = append(u.AdditionalIEs, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (u *UpdatePDPContextResponse) MarshalLen() int {\n\tl := u.Header.MarshalLen() - len(u.Header.Payload)\n\n\tif ie := u.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDDataI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.TEIDCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.GGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.AltGGSNAddressForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.AltGGSNAddressForUserTraffic; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.QoSProfile; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.ChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.AltChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.CommonFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.APNRestriction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.BearerControlMode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.MSInfoChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.EvolvedARPI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.APNAMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := u.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range u.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (u *UpdatePDPContextResponse) SetLength() {\n\tu.Length = uint16(u.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (u *UpdatePDPContextResponse) MessageTypeName() string {\n\treturn \"Update PDP Context Response\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (u *UpdatePDPContextResponse) TEID() uint32 {\n\treturn u.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/update-pdp-context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes UpdatePDPContextResponse into bytes.\n//\n// Deprecated: use UpdatePDPContextResponse.Marshal instead.\nfunc (u *UpdatePDPContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"UpdatePDPContextResponse.Serialize is deprecated. use UpdatePDPContextResponse.Marshal instead\")\n\treturn u.Marshal()\n}\n\n// SerializeTo serializes UpdatePDPContextResponse into bytes given as b.\n//\n// Deprecated: use UpdatePDPContextResponse.MarshalTo instead.\nfunc (u *UpdatePDPContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"UpdatePDPContextResponse.SerializeTo is deprecated. use UpdatePDPContextResponse.MarshalTo instead\")\n\treturn u.MarshalTo(b)\n}\n\n// DecodeUpdatePDPContextResponse decodes bytes as UpdatePDPContextResponse.\n//\n// Deprecated: use ParseUpdatePDPContextResponse instead.\nfunc DecodeUpdatePDPContextResponse(b []byte) (*UpdatePDPContextResponse, error) {\n\tlog.Println(\"DecodeUpdatePDPContextResponse is deprecated. use ParseUpdatePDPContextResponse instead\")\n\treturn ParseUpdatePDPContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as UpdatePDPContextResponse.\n//\n// Deprecated: use UpdatePDPContextResponse.UnmarshalBinary instead.\nfunc (u *UpdatePDPContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"UpdatePDPContextResponse.DecodeFromBytes is deprecated. use UpdatePDPContextResponse.UnmarshalBinary instead\")\n\treturn u.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of UpdatePDPContextResponse.\n//\n// Deprecated: use UpdatePDPContextResponse.MarshalLen instead.\nfunc (u *UpdatePDPContextResponse) Len() int {\n\tlog.Println(\"UpdatePDPContextResponse.Len is deprecated. use UpdatePDPContextResponse.MarshalLen instead\")\n\treturn u.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/update-pdp-context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestUpdatePDPContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewUpdatePDPContextResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv1.ResCauseRequestAccepted),\n\t\t\t\tie.NewRecovery(0),\n\t\t\t\tie.NewTEIDDataI(0xdeadbeef),\n\t\t\t\tie.NewTEIDCPlane(0xdeadbeef),\n\t\t\t\tie.NewGSNAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewGSNAddress(\"2.2.2.2\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x13, 0x00, 0x20, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x01, 0x80,\n\t\t\t\t// Recovery\n\t\t\t\t0x0e, 0x00,\n\t\t\t\t// TEID-U\n\t\t\t\t0x10, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// TEID-C\n\t\t\t\t0x11, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// GSN Address\n\t\t\t\t0x85, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdatePDPContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/message/version-not-supported.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n)\n\n// VersionNotSupported is a VersionNotSupported Header and its IEs above.\ntype VersionNotSupported struct {\n\t*Header\n\tAdditionalIEs []*ie.IE\n}\n\n// NewVersionNotSupported creates a new GTPv1 VersionNotSupported.\nfunc NewVersionNotSupported(teid uint32, seq uint16, ie ...*ie.IE) *VersionNotSupported {\n\tv := &VersionNotSupported{\n\t\tHeader: NewHeader(0x32, MsgTypeVersionNotSupported, teid, seq, nil),\n\t}\n\n\tfor _, i := range ie {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tv.AdditionalIEs = append(v.AdditionalIEs, i)\n\t}\n\n\tv.SetLength()\n\treturn v\n}\n\n// Marshal returns the byte sequence generated from a VersionNotSupported.\nfunc (v *VersionNotSupported) Marshal() ([]byte, error) {\n\tb := make([]byte, v.MarshalLen())\n\tif err := v.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (v *VersionNotSupported) MarshalTo(b []byte) error {\n\tif len(b) < v.MarshalLen() {\n\t\treturn ErrTooShortToMarshal\n\t}\n\tv.Header.Payload = make([]byte, v.MarshalLen()-v.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range v.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(v.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tv.Header.SetLength()\n\treturn v.Header.MarshalTo(b)\n}\n\n// ParseVersionNotSupported decodes a given byte sequence as a VersionNotSupported.\nfunc ParseVersionNotSupported(b []byte) (*VersionNotSupported, error) {\n\tv := &VersionNotSupported{}\n\tif err := v.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn v, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a VersionNotSupported.\nfunc (v *VersionNotSupported) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tv.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(v.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tie, err := ie.ParseMultiIEs(v.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range ie {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tv.AdditionalIEs = append(v.AdditionalIEs, i)\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (v *VersionNotSupported) MarshalLen() int {\n\tl := v.Header.MarshalLen() - len(v.Header.Payload)\n\n\tfor _, ie := range v.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (v *VersionNotSupported) SetLength() {\n\tv.Length = uint16(v.MarshalLen() - 8)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (v *VersionNotSupported) MessageTypeName() string {\n\treturn \"Version Not Supported\"\n}\n\n// TEID returns the TEID in human-readable string.\nfunc (v *VersionNotSupported) TEID() uint32 {\n\treturn v.Header.TEID\n}\n"
  },
  {
    "path": "gtpv1/message/version-not-supported_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes VersionNotSupported into bytes.\n//\n// Deprecated: use VersionNotSupported.Marshal instead.\nfunc (v *VersionNotSupported) Serialize() ([]byte, error) {\n\tlog.Println(\"VersionNotSupported.Serialize is deprecated. use VersionNotSupported.Marshal instead\")\n\treturn v.Marshal()\n}\n\n// SerializeTo serializes VersionNotSupported into bytes given as b.\n//\n// Deprecated: use VersionNotSupported.MarshalTo instead.\nfunc (v *VersionNotSupported) SerializeTo(b []byte) error {\n\tlog.Println(\"VersionNotSupported.SerializeTo is deprecated. use VersionNotSupported.MarshalTo instead\")\n\treturn v.MarshalTo(b)\n}\n\n// DecodeVersionNotSupported decodes bytes as VersionNotSupported.\n//\n// Deprecated: use ParseVersionNotSupported instead.\nfunc DecodeVersionNotSupported(b []byte) (*VersionNotSupported, error) {\n\tlog.Println(\"DecodeVersionNotSupported is deprecated. use ParseVersionNotSupported instead\")\n\treturn ParseVersionNotSupported(b)\n}\n\n// DecodeFromBytes decodes bytes as VersionNotSupported.\n//\n// Deprecated: use VersionNotSupported.UnmarshalBinary instead.\nfunc (v *VersionNotSupported) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"VersionNotSupported.DecodeFromBytes is deprecated. use VersionNotSupported.UnmarshalBinary instead\")\n\treturn v.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of VersionNotSupported.\n//\n// Deprecated: use VersionNotSupported.MarshalLen instead.\nfunc (v *VersionNotSupported) Len() int {\n\tlog.Println(\"VersionNotSupported.Len is deprecated. use VersionNotSupported.MarshalLen instead\")\n\treturn v.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv1/message/version-not-supported_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/testutils\"\n)\n\nfunc TestVersionNotSupported(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewVersionNotSupported(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x32, 0x03, 0x00, 0x04, 0x11, 0x22, 0x33, 0x44,\n\t\t\t\t0x00, 0x01, 0x00, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseVersionNotSupported(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv1/relay.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"log\"\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Relay is to relay packets between two UPlaneConn.\n//\n// Deprecated: Use UPlaneConn.RelayTo() instead.\ntype Relay struct {\n\tmu                  sync.Mutex\n\tcloseCh             chan struct{}\n\tleftConn, rightConn *UPlaneConn\n\tteidPair            map[uint32]*peer\n}\n\n// NewRelay creates a new Relay.\n//\n// Deprecated: Use UPlaneConn.RelayTo() instead.\nfunc NewRelay(leftConn, rightConn *UPlaneConn) *Relay {\n\tlog.Println(\"Relay is deprecated. Use UPlaneConn.RelayTo() instead.\")\n\treturn &Relay{\n\t\tmu:        sync.Mutex{},\n\t\tcloseCh:   make(chan struct{}),\n\t\tleftConn:  leftConn,\n\t\trightConn: rightConn,\n\t\tteidPair:  map[uint32]*peer{},\n\t}\n}\n\n// Run starts listening on both UPlaneConn.\n// Until peer information is registered by AddPeer(), it just drops packets.\n//\n// Deprecated: Use UPlaneConn.RelayTo() instead.\nfunc (r *Relay) Run() {\n\t// from left to right\n\tgo func() {\n\t\tbuf := make([]byte, 1600)\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-r.closed():\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\t// do nothing and go forward.\n\t\t\t}\n\n\t\t\tn, _, teid, err := r.leftConn.ReadFromGTP(buf)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tpeer, ok := r.getPeer(teid)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif _, err := r.rightConn.WriteToGTP(peer.teid, buf[:n], peer.addr); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}()\n\n\t// from right to left\n\tgo func() {\n\t\tbuf := make([]byte, 1600)\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-r.closed():\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\t// do nothing and go forward.\n\t\t\t}\n\n\t\t\tn, _, teid, err := r.rightConn.ReadFromGTP(buf)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tpeer, ok := r.getPeer(teid)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif _, err := r.leftConn.WriteToGTP(peer.teid, buf[:n], peer.addr); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}()\n}\n\n// Close closes Relay. It does not close the UPlaneConn given at first.\n//\n// Deprecated: Use UPlaneConn.RelayTo() instead.\nfunc (r *Relay) Close() error {\n\tif err := r.leftConn.SetReadDeadline(time.Now().Add(1 * time.Millisecond)); err != nil {\n\t\treturn err\n\t}\n\tif err := r.rightConn.SetReadDeadline(time.Now().Add(1 * time.Millisecond)); err != nil {\n\t\treturn err\n\t}\n\tclose(r.closeCh)\n\treturn nil\n}\n\nfunc (r *Relay) closed() <-chan struct{} {\n\treturn r.closeCh\n}\n\n// AddPeer adds a peer information with the TEID contained in the incoming meesage.\n//\n// Deprecated: Use UPlaneConn.RelayTo() instead.\nfunc (r *Relay) AddPeer(teidIn, teidOut uint32, raddr net.Addr) {\n\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\n\tr.teidPair[teidIn] = &peer{teid: teidOut, addr: raddr}\n}\n\nfunc (r *Relay) getPeer(teid uint32) (*peer, bool) {\n\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\n\tp, ok := r.teidPair[teid]\n\treturn p, ok\n}\n"
  },
  {
    "path": "gtpv1/relay_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1_test\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n)\n\nfunc TestRelay(t *testing.T) {\n\tleftAddr, err := net.ResolveUDPAddr(\"udp\", \"127.0.0.11:2152\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\trightAddr, err := net.ResolveUDPAddr(\"udp\", \"127.0.0.12:2152\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tleftConn := gtpv1.NewUPlaneConn(leftAddr)\n\tgo func() {\n\t\tif err := leftConn.ListenAndServe(ctx); err != nil {\n\t\t\tt.Errorf(\"failed to listen on %s: %s\", leftConn.LocalAddr(), err)\n\t\t\treturn\n\t\t}\n\t}()\n\n\trightConn := gtpv1.NewUPlaneConn(rightAddr)\n\tgo func() {\n\t\tif err := rightConn.ListenAndServe(ctx); err != nil {\n\t\t\tt.Errorf(\"failed to listen on %s: %s\", rightConn.LocalAddr(), err)\n\t\t\treturn\n\t\t}\n\t}()\n\n\tif err := leftConn.RelayTo(rightConn, 0x22222222, 0x11111111, rightAddr); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := rightConn.RelayTo(leftConn, 0x11111111, 0x22222222, leftAddr); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// TODO: add tests to check if the traffic goes through conns.\n}\n"
  },
  {
    "path": "gtpv1/testutils/testutils.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package testutils is an internal package to be used for unit tests. Don't use this.\npackage testutils\n\nimport (\n\t\"testing\"\n\n\t\"github.com/pascaldekloe/goe/verify\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n)\n\n// Serializable is just for testing gtpv2.Messages. Don't use this.\ntype Serializable interface {\n\tMarshal() ([]byte, error)\n\tMarshalLen() int\n}\n\n// TestCase is just for testing gtpv2.Messages. Don't use this.\ntype TestCase struct {\n\tDescription string\n\tStructured  Serializable\n\tSerialized  []byte\n}\n\n// ParseFunc is just for testing gtpv2.Messages. Don't use this.\ntype ParseFunc func([]byte) (Serializable, error)\n\n// TestBearerInfo is just for testing gtpv2.Messages. Don't use this.\nvar TestBearerInfo = struct {\n\tTEID uint32\n\tSeq  uint16\n}{0x11223344, 0x00000001}\n\n// Run is just for testing gtpv2.Messages. Don't use this.\nfunc Run(t *testing.T, cases []TestCase, decode ParseFunc) {\n\tt.Helper()\n\n\tfor _, c := range cases {\n\t\tt.Run(c.Description, func(t *testing.T) {\n\t\t\tt.Run(\"Parse\", func(t *testing.T) {\n\t\t\t\tv, err := decode(c.Serialized)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := v, c.Structured; !verify.Values(t, \"\", got, want) {\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Marshal\", func(t *testing.T) {\n\t\t\t\tb, err := c.Structured.Marshal()\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := b, c.Serialized; !verify.Values(t, \"\", got, want) {\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Len\", func(t *testing.T) {\n\t\t\t\tif got, want := c.Structured.MarshalLen(), len(c.Serialized); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Interface\", func(t *testing.T) {\n\t\t\t\t// Ignore *Header and Generic in this tests.\n\t\t\t\tif _, ok := c.Structured.(*message.Header); ok {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif _, ok := c.Structured.(*message.Generic); ok {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tdecoded, err := message.Parse(c.Serialized)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := decoded.Version(), c.Structured.(message.Message).Version(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.MessageType(), c.Structured.(message.Message).MessageType(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.MessageTypeName(), c.Structured.(message.Message).MessageTypeName(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.TEID(), c.Structured.(message.Message).TEID(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv1/tunnel.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"errors\"\n\t\"net\"\n)\n\ntype peer struct {\n\tteid    uint32\n\taddr    net.Addr\n\tsrcConn *UPlaneConn\n}\n\n// RelayTo relays T-PDU type of packet to peer node(specified by raddr) from the UPlaneConn given.\n//\n// By using this, owner of UPlaneConn won't be able to Read and Write the packets that has teidIn.\nfunc (u *UPlaneConn) RelayTo(c *UPlaneConn, teidIn, teidOut uint32, raddr net.Addr) error {\n\tif u.KernelGTP.enabled {\n\t\treturn errors.New(\"cannot call RelayTo when using Kernel GTP-U\")\n\t}\n\n\tu.mu.Lock()\n\tdefer u.mu.Unlock()\n\tif u.relayMap == nil {\n\t\tu.relayMap = map[uint32]*peer{}\n\t}\n\tu.relayMap[teidIn] = &peer{teid: teidOut, addr: raddr, srcConn: c}\n\treturn nil\n}\n\n// CloseRelay stops relaying T-PDU from a conn to conn.\nfunc (u *UPlaneConn) CloseRelay(teidIn uint32) error {\n\tif u.KernelGTP.enabled {\n\t\treturn errors.New(\"cannot call CloseRelay when using Kernel GTP-U\")\n\t}\n\n\tu.mu.Lock()\n\tdelete(u.relayMap, teidIn)\n\tu.mu.Unlock()\n\n\tu.iteiMap.delete(teidIn)\n\treturn nil\n}\n"
  },
  {
    "path": "gtpv1/tunnel_linux.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\n\t\"github.com/vishvananda/netlink\"\n)\n\n// Role is a role for Kernel GTP-U.\ntype Role int\n\n// Role definitions.\nconst (\n\tRoleGGSN Role = iota\n\tRoleSGSN\n)\n\n// EnableKernelGTP enables Linux Kernel GTP-U.\n// Note that this removes all the existing userland tunnels, and cannot be disabled while\n// the program is working (at least at this moment).\n//\n// Using Kernel GTP-U is much more performant than userland, but requires root privilege.\n// After enabled, users should add tunnels by AddTunnel func, and also add appropriate\n// routing entries. For handling downlink traffic on P-GW, for example;\n//\n// ip route add <UE's IP> dev <devname> table <table ID>\n// ip rule add from <SGi side of I/F> lookup <table ID>\n//\n// This let the traffic from SGi side of network I/F to be forwarded to GTP device,\n// and if the UE's IP is known to Kernel GTP-U(by AddTunnel), it is encapsulated and\n// forwarded to the peer(S-GW, in this case).\n//\n// Please see the examples/gw-tester for how each node handles routing from the program.\nfunc (u *UPlaneConn) EnableKernelGTP(devname string, role Role) error {\n\tif u.pktConn == nil {\n\t\tvar err error\n\t\tu.pktConn, err = newPktConn(u.laddr)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tf, err := u.pktConn.File()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to retrieve file from conn: %w\", err)\n\t}\n\n\tu.KernelGTP.Link = &netlink.GTP{\n\t\tLinkAttrs: netlink.LinkAttrs{\n\t\t\tName: devname,\n\t\t},\n\t\tFD1:  int(f.Fd()),\n\t\tRole: int(role),\n\t}\n\n\tif err := netlink.LinkAdd(u.KernelGTP.Link); err != nil {\n\t\t_ = f.Close()\n\t\treturn fmt.Errorf(\"failed to add device %s: %w\", u.KernelGTP.Link.Name, err)\n\t}\n\tif err := netlink.LinkSetUp(u.KernelGTP.Link); err != nil {\n\t\t_ = f.Close()\n\t\treturn fmt.Errorf(\"failed to setup device %s: %w\", u.KernelGTP.Link.Name, err)\n\t}\n\tif err := netlink.LinkSetMTU(u.KernelGTP.Link, 1500); err != nil {\n\t\t_ = f.Close()\n\t\treturn fmt.Errorf(\"failed to set MTU for device %s: %w\", u.KernelGTP.Link.Name, err)\n\t}\n\tu.KernelGTP.connFile = f\n\tu.KernelGTP.enabled = true\n\n\t// remove relayed userland tunnels if exists\n\tif len(u.relayMap) != 0 {\n\t\tu.mu.Lock()\n\t\tu.relayMap = nil\n\t\tu.mu.Unlock()\n\t}\n\n\treturn nil\n}\n\n// AddTunnel adds a GTP-U tunnel with Linux Kernel GTP-U via netlink.\nfunc (u *UPlaneConn) AddTunnel(peerIP, msIP net.IP, otei, itei uint32) error {\n\tif !u.KernelGTP.enabled {\n\t\treturn errors.New(\"cannot call AddTunnel when not using Kernel GTP-U\")\n\t}\n\n\tpdp := &netlink.PDP{\n\t\tVersion:     1,\n\t\tPeerAddress: peerIP,\n\t\tMSAddress:   msIP,\n\t\tOTEI:        otei,\n\t\tITEI:        itei,\n\t}\n\tif err := netlink.GTPPDPAdd(u.KernelGTP.Link, pdp); err != nil {\n\t\treturn fmt.Errorf(\"failed to add tunnel for %s with %s: %w\", msIP, peerIP, err)\n\t}\n\treturn nil\n}\n\n// AddTunnelOverride adds a GTP-U tunnel with Linux Kernel GTP-U via netlink.\n// If there is already an existing tunnel that has the same msIP and/or incoming TEID,\n// this deletes it before adding the tunnel.\nfunc (u *UPlaneConn) AddTunnelOverride(peerIP, msIP net.IP, otei, itei uint32) error {\n\tif !u.KernelGTP.enabled {\n\t\treturn errors.New(\"cannot call AddTunnelOverride when not using Kernel GTP-U\")\n\t}\n\n\tif pdp, _ := netlink.GTPPDPByMSAddress(u.KernelGTP.Link, msIP); pdp != nil {\n\t\t// do nothing even this fails\n\t\t_ = netlink.GTPPDPDel(u.KernelGTP.Link, pdp)\n\t}\n\tif pdp, _ := netlink.GTPPDPByITEI(u.KernelGTP.Link, int(itei)); pdp != nil {\n\t\t// do nothing even this fails\n\t\t_ = netlink.GTPPDPDel(u.KernelGTP.Link, pdp)\n\t}\n\n\treturn u.AddTunnel(peerIP, msIP, otei, itei)\n}\n\n// DelTunnelByITEI deletes a Linux Kernel GTP-U tunnel specified with the incoming TEID.\nfunc (u *UPlaneConn) DelTunnelByITEI(itei uint32) error {\n\tif !u.KernelGTP.enabled {\n\t\treturn errors.New(\"cannot call DelTunnel when not using Kernel GTP-U\")\n\t}\n\n\tpdp, err := netlink.GTPPDPByITEI(u.KernelGTP.Link, int(itei))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to delete tunnel with %d: %w\", itei, err)\n\t}\n\n\tif err := netlink.GTPPDPDel(u.KernelGTP.Link, pdp); err != nil {\n\t\treturn fmt.Errorf(\"failed to delete tunnel for %s: %w\", pdp, err)\n\t}\n\n\tu.iteiMap.delete(itei)\n\treturn nil\n}\n\n// DelTunnelByMSAddress deletes a Linux Kernel GTP-U tunnel specified with the subscriber's IP.\nfunc (u *UPlaneConn) DelTunnelByMSAddress(msIP net.IP) error {\n\tif !u.KernelGTP.enabled {\n\t\treturn errors.New(\"cannot call DelTunnel when not using Kernel GTP-U\")\n\t}\n\n\tpdp, err := netlink.GTPPDPByMSAddress(u.KernelGTP.Link, msIP)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to delete tunnel with %s: %w\", msIP, err)\n\t}\n\titei := pdp.ITEI\n\n\tif err := netlink.GTPPDPDel(u.KernelGTP.Link, pdp); err != nil {\n\t\treturn fmt.Errorf(\"failed to delete tunnel for %s: %w\", pdp, err)\n\t}\n\n\tu.iteiMap.delete(itei)\n\treturn nil\n}\n"
  },
  {
    "path": "gtpv1/u-conn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/vishvananda/netlink\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv1/message\"\n\tv2ie \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"golang.org/x/net/ipv4\"\n\t\"golang.org/x/net/ipv6\"\n)\n\ntype tpduSet struct {\n\traddr   net.Addr\n\tteid    uint32\n\tseq     uint16\n\tpayload []byte\n}\n\ntype pktConn interface {\n\t// WriteToWithDSCPECN writes a packet with payload p to addr using the given DSCP/ECN value.\n\t// WriteToWithDSCPECN can be made to time out and return\n\t// an Error with Timeout() == true after a fixed time limit;\n\t// see SetDeadline and SetWriteDeadline.\n\t// On packet-oriented connections, write timeouts are rare.\n\tWriteToWithDSCPECN(p []byte, addr net.Addr, dscpecn int) (n int, err error)\n\n\t// File returns a copy of the underlying os.File. It is the caller's responsibility to close f when finished.\n\t// Closing c does not affect f, and closing f does not affect c.\n\t// The returned os.File's file descriptor is different from the connection's.\n\t// Attempting to change properties of the original using this duplicate may or may not have the desired effect.\n\tFile() (f *os.File, err error)\n\n\tnet.PacketConn\n}\n\ntype pktConn4 struct {\n\t// mu is the mutex used before Writing to the PacketConn,\n\t// to be sure the right DSCP/ECN value\n\t// is applied before performing the Write.\n\tmu *sync.Mutex\n\n\t// udpConn is the UDPConn used as underlying transport\n\tudpConn *net.UDPConn\n\n\t*ipv4.PacketConn\n}\n\n// ReadFrom implements the io.ReaderFrom ReadFrom method.\nfunc (pkt pktConn4) ReadFrom(b []byte) (n int, src net.Addr, err error) {\n\tn, _, src, err = pkt.PacketConn.ReadFrom(b)\n\treturn n, src, err\n}\n\n// WriteTo implements the PacketConn WriteTo method.\nfunc (pkt pktConn4) WriteTo(b []byte, dst net.Addr) (n int, err error) {\n\treturn pkt.PacketConn.WriteTo(b, nil, dst)\n}\n\n// setDSCPECN sets the DSCP/ECN value used for next writes.\nfunc (pkt pktConn4) setDSCPECN(dscpecs int) error {\n\t// With IPv4, DSCP/ECN is using the TOS field\n\treturn pkt.SetTOS(dscpecs)\n}\n\n// DSCPECN returns the DSCP/ECN value.\nfunc (pkt pktConn4) DSCPECN() (int, error) {\n\t// With IPv4, DSCP/ECN is using the TOS field\n\treturn pkt.TOS()\n}\n\n// WriteToWithDSCPECN implements the pktConn WriteToWithDSCPECN method.\nfunc (pkt pktConn4) WriteToWithDSCPECN(p []byte, addr net.Addr, dscpecn int) (n int, err error) {\n\tpkt.mu.Lock()\n\tdefer pkt.mu.Unlock()\n\toldDSCPECN, err := pkt.DSCPECN()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\terr = pkt.setDSCPECN(dscpecn)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer func() {\n\t\t// set back DSCP/ECN for next write calls\n\t\t_ = pkt.setDSCPECN(oldDSCPECN)\n\t}()\n\treturn pkt.WriteTo(p, addr)\n}\n\n// File returns a copy of the underlying os.File. It is the caller's responsibility to close f when finished.\n// Closing c does not affect f, and closing f does not affect c.\n// The returned os.File's file descriptor is different from the connection's.\n// Attempting to change properties of the original using this duplicate may or may not have the desired effect.\nfunc (pkt pktConn4) File() (f *os.File, err error) {\n\treturn pkt.udpConn.File()\n}\n\ntype pktConn6 struct {\n\t// mu is the mutex used before Writing to the PacketConn,\n\t// to be sure the right DSCP/ECN value\n\t// is applied before performing the Write.\n\tmu *sync.Mutex\n\n\t// udpConn is the UDPConn used as underlying transport.\n\tudpConn *net.UDPConn\n\n\t*ipv6.PacketConn\n}\n\n// ReadFrom implements the io.ReaderFrom ReadFrom method.\nfunc (pkt pktConn6) ReadFrom(b []byte) (n int, src net.Addr, err error) {\n\tn, _, src, err = pkt.PacketConn.ReadFrom(b)\n\treturn n, src, err\n}\n\n// WriteTo implements the PacketConn WriteTo method.\nfunc (pkt pktConn6) WriteTo(b []byte, dst net.Addr) (n int, err error) {\n\treturn pkt.PacketConn.WriteTo(b, nil, dst)\n}\n\n// setDSCPECN sets the DSCP/ECN value used for next writes.\nfunc (pkt pktConn6) setDSCPECN(dscpecs int) error {\n\t// With IPv6, DSCP/ECN is using the Traffic Class field\n\treturn pkt.SetTrafficClass(dscpecs)\n}\n\n// DSCPECN returns the DSCP/ECN value.\nfunc (pkt pktConn6) DSCPECN() (int, error) {\n\t// With IPv6, DSCP/ECN is using the Traffic Class field\n\treturn pkt.TrafficClass()\n}\n\n// WriteToWithDSCPECN implements the pktConn WriteToWithDSCPECN method.\nfunc (pkt pktConn6) WriteToWithDSCPECN(p []byte, addr net.Addr, dscpecn int) (n int, err error) {\n\tpkt.mu.Lock()\n\tdefer pkt.mu.Unlock()\n\toldDSCPECN, err := pkt.DSCPECN()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\terr = pkt.setDSCPECN(dscpecn)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer func() {\n\t\t// set back DSCP/ECN for next write calls\n\t\t_ = pkt.setDSCPECN(oldDSCPECN)\n\t}()\n\treturn pkt.WriteTo(p, addr)\n}\n\n// File returns a copy of the underlying os.File. It is the caller's responsibility to close f when finished.\n// Closing c does not affect f, and closing f does not affect c.\n// The returned os.File's file descriptor is different from the connection's.\n// Attempting to change properties of the original using this duplicate may or may not have the desired effect.\nfunc (pkt pktConn6) File() (f *os.File, err error) {\n\treturn pkt.udpConn.File()\n}\n\n// newPktConn creates a new pktConn initialized with a given local UDP address\nfunc newPktConn(laddr net.Addr) (pktConn, error) {\n\tvar err error\n\tpktC, err := net.ListenPacket(laddr.Network(), laddr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// check if UDPConn is over IPv4 or IPv6\n\taddr, err := net.ResolveUDPAddr(laddr.Network(), laddr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif addr.IP.To4() != nil {\n\t\treturn pktConn4{\n\t\t\tmu:         &sync.Mutex{},\n\t\t\tudpConn:    pktC.(*net.UDPConn),\n\t\t\tPacketConn: ipv4.NewPacketConn(pktC),\n\t\t}, nil\n\t} else if addr.IP.To16() != nil {\n\t\treturn pktConn6{\n\t\t\tmu:         &sync.Mutex{},\n\t\t\tudpConn:    pktC.(*net.UDPConn),\n\t\t\tPacketConn: ipv6.NewPacketConn(pktC),\n\t\t}, nil\n\t}\n\treturn nil, fmt.Errorf(\"laddr must refer to an IP address\")\n}\n\n// UPlaneConn represents a U-Plane Connection of GTPv1.\ntype UPlaneConn struct {\n\tmu      sync.Mutex\n\tladdr   net.Addr\n\tpktConn pktConn\n\t*msgHandlerMap\n\t*iteiMap\n\n\ttpduCh  chan *tpduSet\n\tcloseCh chan struct{}\n\n\trelayMap map[uint32]*peer\n\n\terrIndEnabled bool\n\n\t// for Linux kernel GTP with netlink\n\tKernelGTP\n}\n\n// KernelGTP consists of the Linux Kernel GTP-U related objects.\ntype KernelGTP struct {\n\tenabled  bool\n\tconnFile *os.File\n\tLink     *netlink.GTP\n}\n\n// NewUPlaneConn creates a new UPlaneConn used for server. On client side, use DialUPlane instead.\nfunc NewUPlaneConn(laddr net.Addr) *UPlaneConn {\n\treturn &UPlaneConn{\n\t\tmu:            sync.Mutex{},\n\t\tmsgHandlerMap: newDefaultMsgHandlerMap(),\n\t\titeiMap:       newiteiMap(),\n\t\tladdr:         laddr,\n\n\t\ttpduCh:  make(chan *tpduSet),\n\t\tcloseCh: make(chan struct{}),\n\n\t\terrIndEnabled: true,\n\t}\n}\n\n// DialUPlane sends Echo Request to raddr to check if the endpoint is alive and returns UPlaneConn.\nfunc DialUPlane(ctx context.Context, laddr, raddr net.Addr) (*UPlaneConn, error) {\n\tu := &UPlaneConn{\n\t\tmu:            sync.Mutex{},\n\t\tmsgHandlerMap: newDefaultMsgHandlerMap(),\n\t\titeiMap:       newiteiMap(),\n\t\tladdr:         laddr,\n\n\t\ttpduCh:  make(chan *tpduSet),\n\t\tcloseCh: make(chan struct{}),\n\n\t\terrIndEnabled: true,\n\t}\n\n\t// setup UDPConn first.\n\tvar err error\n\tif u.pktConn == nil {\n\t\tu.pktConn, err = newPktConn(u.laddr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// if no response coming within 5 seconds, returns error.\n\tif err := u.SetReadDeadline(time.Now().Add(5 * time.Second)); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbuf := make([]byte, 1600)\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, nil\n\t\tdefault:\n\t\t\t// go forward\n\t\t}\n\n\t\t// send EchoRequest to raddr.\n\t\tif err := u.EchoRequest(raddr); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tn, _, err := u.ReadFrom(buf)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := u.SetReadDeadline(time.Time{}); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// decode incoming message and let it be handled by default handler funcs.\n\t\tmsg, err := message.Parse(buf[:n])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif _, ok := msg.(*message.EchoResponse); !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tbreak\n\t}\n\n\tgo func() {\n\t\tif err := u.serve(ctx); err != nil {\n\t\t\tlogf(\"fatal error on UPlaneConn %s: %s\", u.LocalAddr(), err)\n\t\t}\n\t}()\n\n\treturn u, nil\n}\n\n// ListenAndServe creates a new GTPv2-C *Conn and start serving.\n// This blocks, and returns error only if it face the fatal one. Non-fatal errors are logged\n// with logger. See SetLogger/EnableLogger/DisableLogger for handling of those logs.\nfunc (u *UPlaneConn) ListenAndServe(ctx context.Context) error {\n\tif u.pktConn == nil {\n\t\tvar err error\n\t\tu.mu.Lock()\n\t\tu.pktConn, err = newPktConn(u.laddr)\n\t\tu.mu.Unlock()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn u.listenAndServe(ctx)\n}\n\nfunc (u *UPlaneConn) listenAndServe(ctx context.Context) error {\n\t// TODO: this func is left for future enhancement.\n\treturn u.serve(ctx)\n}\n\nfunc (u *UPlaneConn) serve(ctx context.Context) error {\n\tgo func() {\n\t\tselect { // ctx is canceled or Close() is called\n\t\tcase <-ctx.Done():\n\t\tcase <-u.closed():\n\t\t}\n\n\t\tif u.KernelGTP.enabled {\n\t\t\tif err := u.KernelGTP.connFile.Close(); err != nil {\n\t\t\t\tlogf(\"error closing GTPFile: %s\", err)\n\t\t\t}\n\t\t\tif err := netlink.LinkDel(u.KernelGTP.Link); err != nil {\n\t\t\t\tlogf(\"error deleting GTPLink: %s\", err)\n\t\t\t}\n\t\t}\n\n\t\t// This doesn't finish for some reason when Kernel GTP is enabled.\n\t\tif u.pktConn != nil {\n\t\t\tif err := u.pktConn.Close(); err != nil {\n\t\t\t\tlogf(\"error closing the underlying conn: %s\", err)\n\t\t\t}\n\t\t}\n\t}()\n\n\tbuf := make([]byte, 1500)\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tcase <-u.closed():\n\t\t\treturn nil\n\t\tdefault:\n\t\t\t// do nothing and go forward.\n\t\t}\n\n\t\tn, raddr, err := u.ReadFrom(buf)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\t// TODO: Use net.ErrClosed instead (available from Go 1.16).\n\t\t\t// https://github.com/golang/go/commit/e9ad52e46dee4b4f9c73ff44f44e1e234815800f\n\t\t\tif strings.Contains(err.Error(), \"use of closed network connection\") {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error reading from UPlaneConn %s: %w\", u.LocalAddr(), err)\n\t\t}\n\n\t\traw := make([]byte, n)\n\t\tcopy(raw, buf)\n\t\tgo func() {\n\t\t\t// just forward T-PDU instead of passing it to reader if relayer is\n\t\t\t// configured and the message type is T-PDU.\n\t\t\tif len(u.relayMap) != 0 && raw[1] == message.MsgTypeTPDU {\n\t\t\t\t// ignore if the packet size is smaller than minimum header size\n\t\t\t\tif n < 11 {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tu.mu.Lock()\n\t\t\t\tpeer, ok := u.relayMap[binary.BigEndian.Uint32(raw[4:8])]\n\t\t\t\tu.mu.Unlock()\n\t\t\t\tif !ok { // pass message to handler if TEID is unknown\n\t\t\t\t\tmsg, err := message.Parse(raw[:n])\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif err := u.handleMessage(raddr, msg); err != nil {\n\t\t\t\t\t\t// should not stop serving with this error\n\t\t\t\t\t\tlogf(\"error handling message on UPlaneConn %s: %v\", u.LocalAddr(), err)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// just use original packet not to get it slow.\n\t\t\t\tbinary.BigEndian.PutUint32(raw[4:8], peer.teid)\n\t\t\t\tif _, err := peer.srcConn.WriteToWithDSCPECN(raw[:n], peer.addr, 0); err != nil {\n\t\t\t\t\t// should not stop serving with this error\n\t\t\t\t\tlogf(\"error sending on UPlaneConn %s: %v\", u.LocalAddr(), err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tmsg, err := message.Parse(raw[:n])\n\t\t\tif err != nil {\n\t\t\t\tlogf(\"error parsing message on UPlaneConn %s: %v\", u.LocalAddr(), err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif err := u.handleMessage(raddr, msg); err != nil {\n\t\t\t\t// should not stop serving with this error\n\t\t\t\tlogf(\"error handling message on UPlaneConn %s: %v\", u.LocalAddr(), err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}()\n\t}\n}\n\n// ReadFrom reads a packet from the connection,\n// copying the payload into p. It returns the number of\n// bytes copied into p and the return address that\n// was on the packet.\n// It returns the number of bytes read (0 <= n <= len(p))\n// and any error encountered. Callers should always process\n// the n > 0 bytes returned before considering the error err.\n// ReadFrom can be made to time out and return\n// an Error with Timeout() == true after a fixed time limit;\n// see SetDeadline and SetReadDeadline.\n//\n// Note that valid GTP-U packets handled by Kernel can NOT be retrieved by this.\nfunc (u *UPlaneConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {\n\treturn u.pktConn.ReadFrom(p)\n}\n\n// ReadFromGTP reads a packet from the connection, copying the payload without\n// GTP header into p. It returns the number of bytes copied into p, the return\n// address that was on the packet, TEID in the GTP header.\n//\n// Note that valid GTP-U packets handled by Kernel can NOT be retrieved by this.\nfunc (u *UPlaneConn) ReadFromGTP(p []byte) (n int, addr net.Addr, teid uint32, err error) {\n\tselect {\n\tcase <-u.closed():\n\t\treturn\n\tcase tpdu, ok := <-u.tpduCh:\n\t\tif !ok {\n\t\t\terr = ErrConnNotOpened\n\t\t\treturn\n\t\t}\n\t\tn = copy(p, tpdu.payload)\n\t\taddr = tpdu.raddr\n\t\tteid = tpdu.teid\n\t\treturn\n\t}\n}\n\n// WriteTo writes a packet with payload p to addr.\n// WriteTo can be made to time out and return\n// an Error with Timeout() == true after a fixed time limit;\n// see SetDeadline and SetWriteDeadline.\n// On packet-oriented connections, write timeouts are rare.\nfunc (u *UPlaneConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {\n\tu.mu.Lock()\n\tdefer u.mu.Unlock()\n\treturn u.pktConn.WriteToWithDSCPECN(p, addr, 0)\n}\n\n// WriteToWithDSCPECN writes a packet with payload p to addr using the given DSCP/ECN value.\n// WriteToWithDSCPECN can be made to time out and return\n// an Error with Timeout() == true after a fixed time limit;\n// see SetDeadline and SetWriteDeadline.\n// On packet-oriented connections, write timeouts are rare.\nfunc (u *UPlaneConn) WriteToWithDSCPECN(p []byte, addr net.Addr, dscpecn int) (n int, err error) {\n\treturn u.pktConn.WriteToWithDSCPECN(p, addr, dscpecn)\n}\n\n// WriteToGTP writes a packet with TEID and payload to addr.\nfunc (u *UPlaneConn) WriteToGTP(teid uint32, p []byte, addr net.Addr) (n int, err error) {\n\tb, err := Encapsulate(teid, p).Marshal()\n\tif err != nil {\n\t\treturn\n\t}\n\n\tif _, err = u.WriteTo(b, addr); err != nil {\n\t\treturn\n\t}\n\treturn len(b), nil\n}\n\n// closed would be used in multiple goroutines.\n// never send struct{}{} to it; instead, use close(u.closeCh).\nfunc (u *UPlaneConn) closed() <-chan struct{} {\n\treturn u.closeCh\n}\n\n// Close closes the connection.\n// Any blocked Read or Write operations will be unblocked and return errors.\nfunc (u *UPlaneConn) Close() error {\n\tu.mu.Lock()\n\tdefer u.mu.Unlock()\n\n\tclose(u.closeCh)\n\n\treturn nil\n}\n\n// LocalAddr returns the local network address.\nfunc (u *UPlaneConn) LocalAddr() net.Addr {\n\treturn u.pktConn.LocalAddr()\n}\n\n// SetDeadline sets the read and write deadlines associated\n// with the connection. It is equivalent to calling both\n// SetReadDeadline and SetWriteDeadline.\n//\n// A deadline is an absolute time after which I/O operations\n// fail with a timeout (see type Error) instead of\n// blocking. The deadline applies to all future and pending\n// I/O, not just the immediately following call to Read or\n// Write. After a deadline has been exceeded, the connection\n// can be refreshed by setting a deadline in the future.\n//\n// An idle timeout can be implemented by repeatedly extending\n// the deadline after successful Read or Write calls.\n//\n// A zero value for t means I/O operations will not time out.\nfunc (u *UPlaneConn) SetDeadline(t time.Time) error {\n\treturn u.pktConn.SetDeadline(t)\n}\n\n// SetReadDeadline sets the deadline for future Read calls\n// and any currently-blocked Read call.\n// A zero value for t means Read will not time out.\nfunc (u *UPlaneConn) SetReadDeadline(t time.Time) error {\n\treturn u.pktConn.SetReadDeadline(t)\n}\n\n// SetWriteDeadline sets the deadline for future Write calls\n// and any currently-blocked Write call.\n// Even if write times out, it may return n > 0, indicating that\n// some of the data was successfully written.\n// A zero value for t means Write will not time out.\nfunc (u *UPlaneConn) SetWriteDeadline(t time.Time) error {\n\treturn u.pktConn.SetWriteDeadline(t)\n}\n\n// AddHandler adds a message handler to *UPlaneConn.\n//\n// By adding HandlerFuncs, *UPlaneConn (and *Session, *Bearer created by the *UPlaneConn) will handle\n// the specified type of message with it's paired HandlerFunc when receiving.\n// Messages without registered handlers are just ignored and discarded and the user will\n// get ErrNoHandlersFound error.\n//\n// This should be performed just after creating *UPlaneConn, otherwise the user cannot retrieve\n// any values, which is in most cases vital to continue working as a node, from the incoming\n// message.\n//\n// HandlerFuncs for EchoResponse and ErrorIndication are registered by default.\n// These HandlerFuncs can be overwritten by specifying message.MsgTypeEchoResponse and/or\n// message.MsgTypeErrorIndication as msgType parameter.\nfunc (u *UPlaneConn) AddHandler(msgType uint8, fn HandlerFunc) {\n\tu.msgHandlerMap.store(msgType, fn)\n}\n\n// AddHandlers adds multiple handler funcs at a time.\n//\n// See AddHandler for detailed usage.\nfunc (u *UPlaneConn) AddHandlers(funcs map[uint8]HandlerFunc) {\n\tfor msgType, fn := range funcs {\n\t\tu.msgHandlerMap.store(msgType, fn)\n\t}\n}\n\nfunc (u *UPlaneConn) handleMessage(senderAddr net.Addr, msg message.Message) error {\n\thandle, ok := u.msgHandlerMap.load(msg.MessageType())\n\tif !ok {\n\t\treturn &HandlerNotFoundError{MsgType: msg.MessageTypeName()}\n\t}\n\n\tif err := handle(u, senderAddr, msg); err != nil {\n\t\treturn fmt.Errorf(\"failed to handle %s: %w\", msg.MessageTypeName(), err)\n\t}\n\n\treturn nil\n}\n\n// EchoRequest sends a EchoRequest.\nfunc (u *UPlaneConn) EchoRequest(raddr net.Addr) error {\n\tb, err := message.NewEchoRequest(0).Marshal()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := u.WriteTo(b, raddr); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// EchoResponse sends a EchoResponse.\nfunc (u *UPlaneConn) EchoResponse(raddr net.Addr) error {\n\tb, err := message.NewEchoResponse(0, ie.NewRecovery(0)).Marshal()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := u.WriteTo(b, raddr); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// ErrorIndication just sends ErrorIndication message.\nfunc (u *UPlaneConn) ErrorIndication(raddr net.Addr, received message.Message) error {\n\tip, _, err := net.SplitHostPort(u.LocalAddr().String())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terrInd, err := message.NewErrorIndication(\n\t\t0, received.Sequence(),\n\t\tie.NewTEIDDataI(received.TEID()),\n\t\tie.NewGSNAddress(ip),\n\t).Marshal()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := u.WriteTo(errInd, raddr); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// RespondTo sends a message(specified with \"toBeSent\" param) in response to\n// a message(specified with \"received\" param).\n//\n// This is to make it easier to handle SequenceNumber.\nfunc (u *UPlaneConn) RespondTo(raddr net.Addr, received, toBeSent message.Message) error {\n\ttoBeSent.SetSequenceNumber(received.Sequence())\n\tb := make([]byte, toBeSent.MarshalLen())\n\tif err := toBeSent.MarshalTo(b); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := u.WriteTo(b, raddr); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// Restarts returns the number of restarts in uint8.\nfunc (u *UPlaneConn) Restarts() uint8 {\n\treturn 0\n}\n\n// NewFTEID creates a new GTPv2 F-TEID with random TEID value that is unique within UPlaneConn.\n// To ensure the uniqueness, don't create in the other way if you once use this method.\n// This is meant to be used for creating F-TEID IE for non-local interface type, such as\n// the ones that are used in U-Plane. For local interface, use (*Conn).NewSenderFTEID instead.\n//\n// Note that in the case there's a lot of Session on the Conn, it may take a long\n// time to find a new unique value.\n//\n// TODO: optimize performance...\nfunc (u *UPlaneConn) NewFTEID(ifType uint8, v4, v6 string) (fteidIE *v2ie.IE) {\n\tvar teid uint32\n\tfor try := uint32(0); try < 0xffff; try++ {\n\t\tconst logEvery = 0xff\n\t\tif try&logEvery == logEvery {\n\t\t\tlogf(\"Generating NewSenderFTEID crossed tries:%d\", try)\n\t\t}\n\n\t\tt := generateRandomUint32()\n\t\tif t == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Try to mark TEID as taken. Fails if something exists\n\t\tif ok := u.iteiMap.tryStore(t, time.Now()); !ok {\n\t\t\tlogf(\"TEID-U: %#08x has already been taken, trying to generate another one...\", t)\n\t\t\tcontinue\n\t\t}\n\n\t\tteid = t\n\t\tbreak\n\t}\n\n\tif teid == 0 {\n\t\treturn nil\n\t}\n\treturn v2ie.NewFullyQualifiedTEID(ifType, teid, v4, v6)\n}\n\nfunc generateRandomUint32() uint32 {\n\tb := make([]byte, 4)\n\tif _, err := rand.Read(b); err != nil {\n\t\treturn 0\n\t}\n\n\treturn binary.BigEndian.Uint32(b)\n}\n\ntype iteiMap struct {\n\tsyncMap sync.Map\n}\n\nfunc newiteiMap() *iteiMap {\n\treturn &iteiMap{}\n}\n\nfunc (t *iteiMap) tryStore(itei uint32, ts time.Time) bool {\n\t_, loaded := t.syncMap.LoadOrStore(itei, ts)\n\treturn !loaded\n}\n\nfunc (t *iteiMap) delete(itei uint32) {\n\tt.syncMap.Delete(itei)\n}\n\n// EnableErrorIndication re-enables automatic sending of\n// Error Indication to unknown messages, which is enabled by\n// default.\n//\n// See also: DisableErrorIndication.\nfunc (u *UPlaneConn) EnableErrorIndication() {\n\tu.mu.Lock()\n\tu.errIndEnabled = true\n\tu.mu.Unlock()\n}\n\n// DisableErrorIndication makes default T-PDU handler stop\n// responding with Error Indication in case of receiving T-PDU\n// with unknown TEID.\n//\n// When disabled, it passes the unhandled T-PDU to user who calls\n// ReadFromGTP instead.\nfunc (u *UPlaneConn) DisableErrorIndication() {\n\tu.mu.Lock()\n\tu.errIndEnabled = false\n\tu.mu.Unlock()\n}\n"
  },
  {
    "path": "gtpv1/u-conn_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1_test\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv1\"\n)\n\ntype testVal struct {\n\tteidIn, teidOut uint32\n\tseq             uint16\n\tpayload         []byte\n}\n\nfunc setup(ctx context.Context) (cliConn, srvConn *gtpv1.UPlaneConn, err error) {\n\tcliAddr, err := net.ResolveUDPAddr(\"udp\", \"127.0.0.1:2152\")\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tsrvAddr, err := net.ResolveUDPAddr(\"udp\", \"127.0.0.2:2152\")\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tgo func() {\n\t\tsrvConn = gtpv1.NewUPlaneConn(srvAddr)\n\t\tsrvConn.DisableErrorIndication()\n\t\tif err := srvConn.ListenAndServe(ctx); err != nil {\n\t\t\treturn\n\t\t}\n\t}()\n\n\t// XXX - waiting for server to be well-prepared, should consider better way.\n\ttime.Sleep(1 * time.Second)\n\tcliConn, err = gtpv1.DialUPlane(ctx, cliAddr, srvAddr)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tcliConn.DisableErrorIndication()\n\n\treturn cliConn, srvConn, nil\n}\n\nfunc TestClientWrite(t *testing.T) {\n\tvar (\n\t\tokCh  = make(chan struct{})\n\t\terrCh = make(chan error)\n\t\tbuf   = make([]byte, 2048)\n\t\ttv    = &testVal{\n\t\t\t0x11111111, 0x22222222, 0x3333,\n\t\t\t[]byte{0xde, 0xad, 0xbe, 0xef},\n\t\t}\n\t)\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\tcliConn, srvConn, err := setup(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgo func(tv *testVal) {\n\t\tn, addr, teid, err := srvConn.ReadFromGTP(buf)\n\t\tif err != nil {\n\t\t\terrCh <- err\n\t\t\treturn\n\t\t}\n\n\t\tif diff := cmp.Diff(n, len(tv.payload)); diff != \"\" {\n\t\t\tt.Error(diff)\n\t\t}\n\t\tif diff := cmp.Diff(addr, cliConn.LocalAddr()); diff != \"\" {\n\t\t\tt.Error(diff)\n\t\t}\n\t\tif diff := cmp.Diff(teid, tv.teidOut); diff != \"\" {\n\t\t\tt.Error(diff)\n\t\t}\n\t\tif diff := cmp.Diff(buf[:n], tv.payload); diff != \"\" {\n\t\t\tt.Error(diff)\n\t\t}\n\t\tokCh <- struct{}{}\n\t}(tv)\n\n\tif _, err := cliConn.WriteToGTP(tv.teidOut, tv.payload, srvConn.LocalAddr()); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tselect {\n\tcase <-okCh:\n\t\treturn\n\tcase err := <-errCh:\n\t\tt.Fatal(err)\n\tcase <-time.After(10 * time.Second):\n\t\tt.Fatal(\"timed out while waiting for response to come\")\n\t}\n}\n"
  },
  {
    "path": "gtpv1/utils.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv1\n\nimport \"github.com/wmnsk/go-gtp/gtpv1/message\"\n\n// Encapsulate encapsulates given payload with GTPv1-U Header and returns message.TPDU.\nfunc Encapsulate(teid uint32, payload []byte) *message.TPDU {\n\tpdu := message.NewTPDU(teid, payload)\n\treturn pdu\n}\n\n// EncapsulateWithExtensionHeader encapsulates given payload and Extension Headers\n// with GTPv1-U Header and returns message.TPDU.\nfunc EncapsulateWithExtensionHeader(teid uint32, payload []byte, extHdrs ...*message.ExtensionHeader) *message.TPDU {\n\tpdu := message.NewTPDUWithExtentionHeader(teid, payload, extHdrs...)\n\treturn pdu\n}\n\n// Decapsulate decapsulates given bytes and returns TEID and Payload.\nfunc Decapsulate(b []byte) (uint32, []byte, error) {\n\theader, err := message.ParseHeader(b)\n\tif err != nil {\n\t\treturn 0, nil, err\n\t}\n\n\tif header.Type != message.MsgTypeTPDU {\n\t\treturn 0, nil, message.ErrInvalidMessageType\n\t}\n\treturn header.TEID, header.Payload, nil\n}\n\n// DecapsulateWithExtensionHeader decapsulates given bytes and returns TEID,\n// Payload, and Extension Headers.\n// It is always safe to use this even if there may be no Extension Headers.\nfunc DecapsulateWithExtensionHeader(b []byte) (uint32, []byte, []*message.ExtensionHeader, error) {\n\th, err := message.ParseHeader(b)\n\tif err != nil {\n\t\treturn 0, nil, nil, err\n\t}\n\n\tif h.Type != message.MsgTypeTPDU {\n\t\treturn 0, nil, nil, message.ErrInvalidMessageType\n\t}\n\treturn h.TEID, h.Payload, h.ExtensionHeaders, nil\n}\n"
  },
  {
    "path": "gtpv2/README.md",
    "content": "# gtpv2: GTPv2 in Golang\n\nPackage v2 provides simple and painless handling of GTPv2-C protocol in pure Golang.\n\n## Getting Started\n\n_Working examples are available in [example](../examples) directory, which might be the better instruction for developers._\n\n### Opening a connection\n\n#### Client\n\n`Dial` opens a connection between the specified peer by confirming the peer is alive by Echo Request/Response exchange. If you don't need Echo, see Server section.\n\n```go\n// Note that the conn is not bound to raddr. to let a Conn to be able to communicate with multiple peers.\n// Interface type is required here to let Conn know which is the local interface type.\nconn, err := gtpv2.Dial(ctx, laddr, raddr, gtpv2.IFTypeS11MMEGTPC, 0)\nif err != nil {\n    // ...\n}\n```\n\n#### Server \n\nRetrieve `Conn` with `NewConn`, and `ListenAndServe` to start listening.\n\n```go\n// Interface type is required here to let Conn know which is the local interface type.\nsrvConn := gtpv2.NewConn(srvAddr, gtpv2.IFTypeS11MMEGTPC, 0)\nif err := srvConn.ListenAndServe(ctx); err != nil {\n    // ...\n}\n```\n\n### Handling incoming messages\n\nPrepare functions that comform to [`HandlerFunc`](https://pkg.go.dev/github.com/wmnsk/go-gtp/gtpv2#Conn.AddHandler), and register them to `Conn` with `AddHandler`. This should be done as soon as you get `Conn` not to miss the incoming messages.\n\n`HandlerFunc` is to handle the incoming messages by message type. See [example](../examples) for how it is like.  \nAlso consider using `AddHandlers` when you have many `HandlerFunc`s.\n\n```go\n// write what you expect to do on receiving a message. Handlers should be added per message type.\n// by default, Echo Request/Response and Version Not Supported Indication is handled automatically.\nconn.AddHandler(\n    // first param is the type of message. give number in uint8 or use gtpgtpv2.MsgTypeXXX.\n    messages.MsgTypeCreateSessionResponse,\n    // second param is the HandlerFunc to describe how you handle the message coming from peer.\n    func(c *gtpv2.Conn, senderAddr net.Addr, msg messages.Message) error {\n        // Do what you want with CreateSessionResponse message here.\n        // see examples directly for functional examples\n    },\n)\n```\n\n### Manipulating sessions\n\nWith `Conn`, you can create, modify, delete GTPv2-C sessions and bearers with the built-in methods.\n\n#### Session creation\n\n`CreateSession` creates a Session, while storing values given as IEs and creating a default bearer.\nIn the following call, for example, IMSI and TEID for S1-U eNB is stored in the created `Session`.\n\n```go\nsession, err := c.CreateSession(\n    // put IEs required for your implementation here.\n    // it is easier to use constructors in ie package.\n    ie.NewIMSI(\"123451234567890\"),\n    \n    // or, you can use ie.New() to create an IE without type-specific constructor.\n    // put the type of IE, flags/instance, and payload as the parameters.\n    ie.New(ie.ExtendedTraceInformation, 0x00, []byte{0xde, 0xad, 0xbe, 0xef}),\n    \n    // to set the instance to IE created with message-specific constructor, WithInstance()\n    // may be your help.\n    ie.NewIMSI(\"123451234567890\").WithInstance(1), // no one wants to set instance to IMSI, though.\n\n    // don't forget to contain the Sender F-TEID, as it is used to distinguish the incoming\n    // message by Conn.\n    //\n    // to be secure, TEID should be generated with random values, without conflicts in a Conn.\n    // to achieve that, gtpv2 provides NewFTEID() which returns F-TEID in *ie.IE.\n    s11Conn.NewFTEID(gtpv2.IFTypeS11MMEGTPC, mmeIP, \"\"),\n)\nif err != nil {\n    // ...\n}\n```\n\n#### Session deletion / Bearer modification\n\n`DeleteSession` and `ModifyBearer` methods are provided to send each message as easy as possible.\nUnlike `CreateSession`, they don't manipulate the Session information automatically.\n\n### Opening a U-Plane connection\n\n_See [v1/README.md](../gtpv1/README.md#opening-a-u-plane-connection)._\n\n## Supported Features\n\nThe following Messages marked with \"Yes\" are currently available with their own useful constructors.\n\n_Even there are some missing Messages, you can create any kind of Message by using `messages.NewGeneric()`._\n\n### Messages\n\n| ID      | Name                                            | Supported |\n|---------|-------------------------------------------------|-----------|\n| 0       | (Spare/Reserved)                                | -         |\n| 1       | Echo Request                                    | Yes       |\n| 2       | Echo Response                                   | Yes       |\n| 3       | Version Not Supported Indication                | Yes       |\n| 4-16    | (Spare/Reserved)                                | -         |\n| 17-24   | (Spare/Reserved)                                | -         |\n| 25-31   | (Spare/Reserved)                                | -         |\n| 32      | Create Session Request                          | Yes       |\n| 33      | Create Session Response                         | Yes       |\n| 34      | Modify Bearer Request                           | Yes       |\n| 35      | Modify Bearer Response                          | Yes       |\n| 36      | Delete Session Request                          | Yes       |\n| 37      | Delete Session Response                         | Yes       |\n| 38      | Change Notification Request                     |           |\n| 39      | Change Notification Response                    |           |\n| 40      | Remote UE Report Notification                   |           |\n| 41      | Remote UE Report Acknowledge                    |           |\n| 42-63   | (Spare/Reserved)                                | -         |\n| 64      | Modify Bearer Command                           | Yes       |\n| 65      | Modify Bearer Failure Indication                | Yes       |\n| 66      | Delete Bearer Command                           | Yes       |\n| 67      | Delete Bearer Failure Indication                | Yes       |\n| 68      | Bearer Resource Command                         |           |\n| 69      | Bearer Resource Failure Indication              |           |\n| 70      | Downlink Data Notification Failure Indication   | Yes       |\n| 71      | Trace Session Activation                        |           |\n| 72      | Trace Session Deactivation                      |           |\n| 73      | Stop Paging Indication                          | Yes       |\n| 74-94   | (Spare/Reserved)                                | -         |\n| 95      | Create Bearer Request                           | Yes       |\n| 96      | Create Bearer Response                          | Yes       |\n| 97      | Update Bearer Request                           | Yes       |\n| 98      | Update Bearer Response                          | Yes       |\n| 99      | Delete Bearer Request                           | Yes       |\n| 100     | Delete Bearer Response                          | Yes       |\n| 101     | Delete PDN Connection Set Request               | Yes       |\n| 102     | Delete PDN Connection Set Response              | Yes       |\n| 103     | PGW Downlink Triggering Notification            |           |\n| 104     | PGW Downlink Triggering Acknowledge             |           |\n| 105-127 | (Spare/Reserved)                                | -         |\n| 128     | Identification Request                          |           |\n| 129     | Identification Response                         |           |\n| 130     | Context Request                                 | Yes       |\n| 131     | Context Response                                | Yes       |\n| 132     | Context Acknowledge                             | Yes       |\n| 133     | Forward Relocation Request                      |           |\n| 134     | Forward Relocation Response                     |           |\n| 135     | Forward Relocation Complete Notification        |           |\n| 136     | Forward Relocation Complete Acknowledge         |           |\n| 137     | Forward Access Context Notification             |           |\n| 138     | Forward Access Context Acknowledge              |           |\n| 139     | Relocation Cancel Request                       |           |\n| 140     | Relocation Cancel Response                      |           |\n| 141     | Configuration Transfer Tunnel                   |           |\n| 142-148 | (Spare/Reserved)                                | -         |\n| 149     | Detach Notification                             | Yes       |\n| 150     | Detach Acknowledge                              | Yes       |\n| 151     | CS Paging Indication                            |           |\n| 152     | RAN Information Relay                           |           |\n| 153     | Alert MME Notification                          |           |\n| 154     | Alert MME Acknowledge                           |           |\n| 155     | UE Activity Notification                        |           |\n| 156     | UE Activity Acknowledge                         |           |\n| 157     | ISR Status Indication                           |           |\n| 158     | UE Registration Query Request                   |           |\n| 159     | UE Registration Query Response                  |           |\n| 160     | Create Forwarding Tunnel Request                |           |\n| 161     | Create Forwarding Tunnel Response               |           |\n| 162     | Suspend Notification                            | Yes       |\n| 163     | Suspend Acknowledge                             | Yes       |\n| 164     | Resume Notification                             | Yes       |\n| 165     | Resume Acknowledge                              | Yes       |\n| 166     | Create Indirect Data Forwarding Tunnel Request  |           |\n| 167     | Create Indirect Data Forwarding Tunnel Response |           |\n| 168     | Delete Indirect Data Forwarding Tunnel Request  |           |\n| 169     | Delete Indirect Data Forwarding Tunnel Response |           |\n| 170     | Release Access Bearers Request                  | Yes       |\n| 171     | Release Access Bearers Response                 | Yes       |\n| 172-175 | (Spare/Reserved)                                | -         |\n| 176     | Downlink Data Notification                      | Yes       |\n| 177     | Downlink Data Notification Acknowledge          | Yes       |\n| 178     | (Spare/Reserved)                                | -         |\n| 179     | PGW Restart Notification                        | Yes       |\n| 180     | PGW Restart Notification Acknowledge            | Yes       |\n| 181-199 | (Spare/Reserved)                                | -         |\n| 200     | Update PDN Connection Set Request               | Yes       |\n| 201     | Update PDN Connection Set Response              | Yes       |\n| 202-210 | (Spare/Reserved)                                | -         |\n| 211     | Modify Access Bearers Request                   | Yes       |\n| 212     | Modify Access Bearers Response                  | Yes       |\n| 213-230 | (Spare/Reserved)                                | -         |\n| 231     | MBMS Session Start Request                      |           |\n| 232     | MBMS Session Start Response                     |           |\n| 233     | MBMS Session Update Request                     |           |\n| 234     | MBMS Session Update Response                    |           |\n| 235     | MBMS Session Stop Request                       |           |\n| 236     | MBMS Session Stop Response                      |           |\n| 237-239 | (Spare/Reserved)                                | -         |\n| 240-247 | (Spare/Reserved)                                | -         |\n| 248-255 | (Spare/Reserved)                                | -         |\n\n### Information Elements\n\nThe following Information Elements marked with \"Yes\" are currently available with their own useful constructors.\n\n_Even there are some missing IEs, you can create any kind of IEs by using `ie.New()` function or by initializing ie.IE directly._\n\n| ID      | Name                                                           | Supported |\n|---------|----------------------------------------------------------------|-----------|\n| 0       | (Spare/Reserved)                                               | -         |\n| 1       | International Mobile Subscriber Identity (IMSI)                | Yes       |\n| 2       | Cause                                                          | Yes       |\n| 3       | Recovery (Restart Counter)                                     | Yes       |\n| 4-34    | (Spare/Reserved)                                               | -         |\n| 35-50   | (Spare/Reserved)                                               | -         |\n| 51      | STN-SR                                                         |           |\n| 52-70   | (Spare/Reserved)                                               | -         |\n| 71      | Access Point Name (APN)                                        | Yes       |\n| 72      | Aggregate Maximum Bit Rate (AMBR)                              | Yes       |\n| 73      | EPS Bearer ID (EBI)                                            | Yes       |\n| 74      | IP Address                                                     | Yes       |\n| 75      | Mobile Equipment Identity (MEI)                                | Yes       |\n| 76      | MSISDN                                                         | Yes       |\n| 77      | Indication                                                     | Yes       |\n| 78      | Protocol Configuration Options (PCO)                           | Yes       |\n| 79      | PDN Address Allocation (PAA)                                   | Yes       |\n| 80      | Bearer Level Quality of Service (Bearer QoS)                   | Yes       |\n| 81      | Flow Quality of Service (Flow QoS)                             | Yes       |\n| 82      | RAT Type                                                       | Yes       |\n| 83      | Serving Network                                                | Yes       |\n| 84      | EPS Bearer Level Traffic Flow Template (Bearer TFT)            | Yes       |\n| 85      | Traffic Aggregation Description (TAD)                          |           |\n| 86      | User Location Information (ULI)                                | Yes       |\n| 87      | Fully Qualified Tunnel Endpoint Identifier (F-TEID)            | Yes       |\n| 88      | TMSI                                                           | Yes       |\n| 89      | Global CN-Id                                                   | Yes       |\n| 90      | S103 PDN Data Forwarding Info (S103PDF)                        | Yes       |\n| 91      | S1-U Data Forwarding Info (S1UDF)                              | Yes       |\n| 92      | Delay Value                                                    | Yes       |\n| 93      | Bearer Context                                                 | Yes       |\n| 94      | Charging ID                                                    | Yes       |\n| 95      | Charging Characteristics                                       | Yes       |\n| 96      | Trace Information                                              |           |\n| 97      | Bearer Flags                                                   | Yes       |\n| 98      | (Spare/Reserved)                                               | -         |\n| 99      | PDN Type                                                       | Yes       |\n| 100     | Procedure Transaction ID                                       | Yes       |\n| 101     | (Spare/Reserved)                                               | -         |\n| 102     | (Spare/Reserved)                                               | -         |\n| 103     | MM Context (GSM Key and Triplets)                              |           |\n| 104     | MM Context (UMTS Key, Used Cipher and Quintuplets)             |           |\n| 105     | MM Context (GSM Key, Used Cipher and Quintuplets)              |           |\n| 106     | MM Context (UMTS Key and Quintuplets)                          |           |\n| 107     | MM Context (EPS Security Context, Quadruplets and Quintuplets) |           |\n| 108     | MM Context (UMTS Key, Quadruplets and Quintuplets)             |           |\n| 109     | PDN Connection                                                 |           |\n| 110     | PDU Numbers                                                    |           |\n| 111     | Packet TMSI                                                    | Yes       |\n| 112     | P-TMSI Signature                                               | Yes       |\n| 113     | Hop Counter                                                    | Yes       |\n| 114     | UE Time Zone                                                   | Yes       |\n| 115     | Trace Reference                                                | Yes       |\n| 116     | Complete Request Message                                       |           |\n| 117     | GUTI                                                           | Yes       |\n| 118     | F-Container                                                    |           |\n| 119     | F-Cause                                                        |           |\n| 120     | PLMN ID                                                        | Yes       |\n| 121     | Target Identification                                          |           |\n| 122     | (Spare/Reserved)                                               | -         |\n| 123     | Packet Flow ID                                                 |           |\n| 124     | RAB Context                                                    |           |\n| 125     | Source RNC PDCP Context Info                                   |           |\n| 126     | Port Number                                                    | Yes       |\n| 127     | APN Restriction                                                | Yes       |\n| 128     | Selection Mode                                                 | Yes       |\n| 129     | Source Identification                                          |           |\n| 130     | (Spare/Reserved)                                               | -         |\n| 131     | Change Reporting Action                                        |           |\n| 132     | Fully Qualified PDN Connection Set Identifier (FQ-CSID)        | Yes       |\n| 133     | Channel Needed                                                 |           |\n| 134     | eMLPP Priority                                                 |           |\n| 135     | Node Type                                                      | Yes       |\n| 136     | Fully Qualified Domain Name (FQDN)                             | Yes       |\n| 137     | Transaction Identifier (TI)                                    |           |\n| 138     | MBMS Session Duration                                          |           |\n| 139     | MBMS Service Area                                              |           |\n| 140     | MBMS Session Identifier                                        |           |\n| 141     | MBMS Flow Identifier                                           |           |\n| 142     | MBMS IP Multicast Distribution                                 |           |\n| 143     | MBMS Distribution Acknowledge                                  |           |\n| 144     | RFSP Index                                                     |           |\n| 145     | User CSG Information (UCI)                                     | Yes       |\n| 146     | CSG Information Reporting Action                               |           |\n| 147     | CSG ID                                                         | Yes       |\n| 148     | CSG Membership Indication (CMI)                                | Yes       |\n| 149     | Service Indicator                                              | Yes       |\n| 150     | Detach Type                                                    | Yes       |\n| 151     | Local Distinguished Name (LDN)                                 | Yes       |\n| 152     | Node Features                                                  | Yes       |\n| 153     | MBMS Time to Data Transfer                                     |           |\n| 154     | Throttling                                                     | Yes       |\n| 155     | Allocation/Retention Priority (ARP)                            | Yes       |\n| 156     | EPC Timer                                                      | Yes       |\n| 157     | Signalling Priority Indication                                 |           |\n| 158     | Temporary Mobile Group Identity (TMGI)                         |           |\n| 159     | Additional MM context for SRVCC                                |           |\n| 160     | Additional flags for SRVCC                                     |           |\n| 161     | (Spare/Reserved)                                               | -         |\n| 162     | MDT Configuration                                              |           |\n| 163     | Additional Protocol Configuration Options (APCO)               |           |\n| 164     | Absolute Time of MBMS Data Transfer                            |           |\n| 165     | H(e)NB Information Reporting                                   |           |\n| 166     | IPv4 Configuration Parameters (IP4CP)                          |           |\n| 167     | Change to Report Flags                                         |           |\n| 168     | Action Indication                                              |           |\n| 169     | TWAN Identifier                                                |           |\n| 170     | ULI Timestamp                                                  | Yes       |\n| 171     | MBMS Flags                                                     |           |\n| 172     | RAN/NAS Cause                                                  | Yes       |\n| 173     | CN Operator Selection Entity                                   |           |\n| 174     | Trusted WLAN Mode Indication                                   |           |\n| 175     | Node Number                                                    |           |\n| 176     | Node Identifier                                                |           |\n| 177     | Presence Reporting Area Action                                 |           |\n| 178     | Presence Reporting Area Information                            |           |\n| 179     | TWAN Identifier Timestamp                                      |           |\n| 180     | Overload Control Information                                   |           |\n| 181     | Load Control Information                                       |           |\n| 182     | Metric                                                         |           |\n| 183     | Sequence Number                                                |           |\n| 184     | APN and Relative Capacity                                      |           |\n| 185     | WLAN Offloadability Indication                                 |           |\n| 186     | Paging and Service Information                                 | Yes       |\n| 187     | Integer Number                                                 | Yes       |\n| 188     | Millisecond Time Stamp                                         |           |\n| 189     | Monitoring Event Information                                   |           |\n| 190     | ECGI List                                                      |           |\n| 191     | Remote UE Context                                              |           |\n| 192     | Remote User ID                                                 |           |\n| 193     | Remote UE IP information                                       |           |\n| 194     | CIoT Optimizations Support Indication                          |           |\n| 195     | SCEF PDN Connection                                            |           |\n| 196     | Header Compression Configuration                               |           |\n| 197     | Extended Protocol Configuration Options (ePCO)                 |           |\n| 198     | Serving PLMN Rate Control                                      |           |\n| 199     | Counter                                                        |           |\n| 200     | Mapped UE Usage Type                                           |           |\n| 201     | Secondary RAT Usage Data Report                                |           |\n| 202     | UP Function Selection Indication Flags                         |           |\n| 203     | Maximum Packet Loss Rate                                       |           |\n| 204     | APN Rate Control Status                                        |           |\n| 205     | Extended Trace Information                                     |           |\n| 206     | Monitoring Event Extension Information                         |           |\n| 207     | Additional RRM Policy Index                                    |           |\n| 208     | V2X Context                                                    |           |\n| 209     | PC5 QoS Parameters                                             |           |\n| 210     | Services Authorized                                            |           |\n| 211     | Bit Rate                                                       |           |\n| 212     | PC5 QoS Flow                                                   |           |\n| 213-253 | (Spare/Reserved)                                               | -         |\n| 254     | (Spare/Reserved)                                               | -         |\n| 255     | Private Extension                                              | Yes       |\n"
  },
  {
    "path": "gtpv2/bearer.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\nimport (\n\t\"net\"\n)\n\n// QoSProfile represents a QoS-related information that belongs to a Bearer.\ntype QoSProfile struct {\n\tPCI, PVI bool\n\tPL, QCI  uint8\n\t// Max bit rate for Uplink and Donwlink\n\tMBRUL, MBRDL uint64\n\t// Guaranteed bit rate for Uplink and Donwlink\n\tGBRUL, GBRDL uint64\n}\n\n// Bearer represents a GTPv2 bearer.\ntype Bearer struct {\n\traddr           net.Addr\n\tteidIn, teidOut uint32\n\n\tEBI               uint8\n\tSubscriberIP, APN string\n\tChargingID        uint32\n\t*QoSProfile\n}\n\n// NewBearer creates a new Bearer.\nfunc NewBearer(ebi uint8, apn string, qos *QoSProfile) *Bearer {\n\treturn &Bearer{\n\t\tEBI: ebi, APN: apn, QoSProfile: qos,\n\t}\n}\n\n// RemoteAddress returns the remote address associated with Bearer.\nfunc (b *Bearer) RemoteAddress() net.Addr {\n\treturn b.raddr\n}\n\n// SetRemoteAddress sets the remote address associated with Bearer.\nfunc (b *Bearer) SetRemoteAddress(raddr net.Addr) {\n\tb.raddr = raddr\n}\n\n// IncomingTEID returns the incoming TEID associated with Bearer.\nfunc (b *Bearer) IncomingTEID() uint32 {\n\treturn b.teidIn\n}\n\n// SetIncomingTEID sets the incoming TEID associated with Bearer.\nfunc (b *Bearer) SetIncomingTEID(teid uint32) {\n\tb.teidIn = teid\n}\n\n// OutgoingTEID returns the outgoing TEID associated with Bearer.\nfunc (b *Bearer) OutgoingTEID() uint32 {\n\treturn b.teidOut\n}\n\n// SetOutgoingTEID sets the outgoing TEID associated with Bearer.\nfunc (b *Bearer) SetOutgoingTEID(teid uint32) {\n\tb.teidOut = teid\n}\n"
  },
  {
    "path": "gtpv2/conn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// Conn represents a GTPv2-C connection.\n//\n// Conn provides the automatic handling of message by adding handlers to it with\n// AddHandler(s). See AddHandler for detailed usage.\n//\n// Conn also provides the functions to manage Sessions/Bearers that works over the\n// connection(=between a node to another).\n// See the docs of CreateSession, AddSession, DeleteSession methods for details.\ntype Conn struct {\n\tmu      sync.Mutex\n\tladdr   net.Addr\n\tpktConn net.PacketConn\n\t*imsiSessionMap\n\t*iteiSessionMap\n\tlocalIfType uint8\n\n\tvalidationEnabled bool\n\n\tcloseCh chan struct{}\n\t*msgHandlerMap\n\n\t// sequence is the last SequenceNumber used in the request.\n\t//\n\t// TS29.274 7.6  Reliable Delivery of Signalling Messages;\n\t// The Sequence Number shall be unique for each outstanding Initial message sourced\n\t// from the same IP/UDP endpoint(=Conn).\n\tsequence uint32\n\n\t// RestartCounter is the RestartCounter value in Recovery IE, which represents how many\n\t// times the GTPv2-C endpoint is restarted.\n\tRestartCounter uint8\n}\n\n// NewConn creates a new Conn used for server. On client side, use Dial instead.\nfunc NewConn(laddr net.Addr, localIfType, counter uint8) *Conn {\n\treturn &Conn{\n\t\tmu:                sync.Mutex{},\n\t\tladdr:             laddr,\n\t\timsiSessionMap:    newimsiSessionMap(),\n\t\titeiSessionMap:    newiteiSessionMap(),\n\t\tlocalIfType:       localIfType,\n\t\tvalidationEnabled: true,\n\t\tcloseCh:           make(chan struct{}),\n\t\tmsgHandlerMap:     newDefaultMsgHandlerMap(),\n\t\tsequence:          0,\n\t\tRestartCounter:    counter,\n\t}\n}\n\n// Dial sends Echo Request to raddr to check if the endpoint is alive and returns Conn.\n//\n// It does not bind the raddr to the underlying connection, which enables a Conn to\n// send to/receive from multiple peers with single laddr.\n//\n// If Echo exchange is unnecessary, use NewConn and ListenAndServe instead.\nfunc Dial(ctx context.Context, laddr, raddr net.Addr, localIfType, counter uint8) (*Conn, error) {\n\tc := &Conn{\n\t\tmu:                sync.Mutex{},\n\t\tladdr:             laddr,\n\t\timsiSessionMap:    newimsiSessionMap(),\n\t\titeiSessionMap:    newiteiSessionMap(),\n\t\tlocalIfType:       localIfType,\n\t\tvalidationEnabled: true,\n\t\tcloseCh:           make(chan struct{}),\n\t\tmsgHandlerMap:     newDefaultMsgHandlerMap(),\n\t\tsequence:          0,\n\t\tRestartCounter:    counter,\n\t}\n\n\t// setup underlying connection first.\n\t// not using net.Dial, as it binds src/dst IP:Port, which makes it harder to\n\t// handle multiple connections with a Conn.\n\tvar err error\n\tc.pktConn, err = net.ListenPacket(c.laddr.Network(), c.laddr.String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// send EchoRequest to raddr.\n\tif _, err := c.EchoRequest(raddr); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbuf := make([]byte, 1500)\n\n\t// if no response coming within 3 seconds, returns error without retrying.\n\tif err := c.pktConn.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {\n\t\treturn nil, err\n\t}\n\tn, raddr, err := c.pktConn.ReadFrom(buf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := c.pktConn.SetReadDeadline(time.Time{}); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// decode incoming message and let it be handled by default handler funcs.\n\tmsg, err := message.Parse(buf[:n])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := c.handleMessage(raddr, msg); err != nil {\n\t\treturn nil, err\n\t}\n\n\tgo func() {\n\t\tif err := c.Serve(ctx); err != nil {\n\t\t\tlogf(\"fatal error on Conn %s: %s\", c.LocalAddr(), err)\n\t\t}\n\t}()\n\treturn c, nil\n}\n\n// ListenAndServe creates a new GTPv2-C Conn and start serving background.\nfunc (c *Conn) ListenAndServe(ctx context.Context) error {\n\terr := c.Listen(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn c.listenAndServe(ctx)\n}\n\n// Listen creates a new GTPv2-C Conn\nfunc (c *Conn) Listen(ctx context.Context) error {\n\tvar err error\n\tc.mu.Lock()\n\tc.pktConn, err = net.ListenPacket(c.laddr.Network(), c.laddr.String())\n\tc.mu.Unlock()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (c *Conn) listenAndServe(ctx context.Context) error {\n\t// TODO: this func is left for future enhancement.\n\treturn c.Serve(ctx)\n}\n\nfunc (c *Conn) closed() <-chan struct{} {\n\treturn c.closeCh\n}\n\n// Serve starts serving GTPv2 connection.\nfunc (c *Conn) Serve(ctx context.Context) error {\n\tgo func() {\n\t\tselect { // ctx is canceled or Close() is called\n\t\tcase <-ctx.Done():\n\t\tcase <-c.closed():\n\t\t}\n\n\t\tif err := c.pktConn.Close(); err != nil {\n\t\t\tlogf(\"error closing the underlying conn: %s\", err)\n\t\t}\n\t}()\n\n\tbuf := make([]byte, 1500)\n\tfor {\n\t\tn, raddr, err := c.pktConn.ReadFrom(buf)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif errors.Is(err, net.ErrClosed) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error reading from Conn %s: %w\", c.LocalAddr(), err)\n\t\t}\n\n\t\traw := make([]byte, n)\n\t\tcopy(raw, buf)\n\t\tgo func() {\n\t\t\tmsg, err := message.Parse(raw)\n\t\t\tif err != nil {\n\t\t\t\tlogf(\"error parsing the message: %v, %x\", err, raw)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif err := c.handleMessage(raddr, msg); err != nil {\n\t\t\t\tlogf(\"error handling message on Conn %s: %v\", c.LocalAddr(), err)\n\t\t\t}\n\t\t}()\n\t}\n}\n\n// ReadFrom reads a packet from the connection,\n// copying the payload into p. It returns the number of\n// bytes copied into p and the return address that\n// was on the packet.\n// It returns the number of bytes read (0 <= n <= len(p))\n// and any error encountered. Callers should always process\n// the n > 0 bytes returned before considering the error err.\n// ReadFrom can be made to time out and return\n// an Error with Timeout() == true after a fixed time limit;\n// see SetDeadline and SetReadDeadline.\nfunc (c *Conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {\n\treturn c.pktConn.ReadFrom(p)\n}\n\n// WriteTo writes a packet with payload p to addr.\n// WriteTo can be made to time out and return\n// an Error with Timeout() == true after a fixed time limit;\n// see SetDeadline and SetWriteDeadline.\n// On packet-oriented connections, write timeouts are rare.\nfunc (c *Conn) WriteTo(p []byte, addr net.Addr) (n int, err error) {\n\treturn c.pktConn.WriteTo(p, addr)\n}\n\n// Close closes the connection.\n// Any blocked Read or Write operations will be unblocked and return errors.\nfunc (c *Conn) Close() error {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tclose(c.closeCh)\n\n\treturn nil\n}\n\n// LocalAddr returns the local network address.\nfunc (c *Conn) LocalAddr() net.Addr {\n\treturn c.pktConn.LocalAddr()\n}\n\n// SetDeadline sets the read and write deadlines associated\n// with the connection. It is equivalent to calling both\n// SetReadDeadline and SetWriteDeadline.\n//\n// A deadline is an absolute time after which I/O operations\n// fail with a timeout (see type Error) instead of\n// blocking. The deadline applies to all future and pending\n// I/O, not just the immediately following call to Read or\n// Write. After a deadline has been exceeded, the connection\n// can be refreshed by setting a deadline in the future.\n//\n// An idle timeout can be implemented by repeatedly extending\n// the deadline after successful Read or Write calls.\n//\n// A zero value for t means I/O operations will not time out.\nfunc (c *Conn) SetDeadline(t time.Time) error {\n\treturn c.pktConn.SetDeadline(t)\n}\n\n// SetReadDeadline sets the deadline for future Read calls\n// and any currently-blocked Read call.\n// A zero value for t means Read will not time out.\nfunc (c *Conn) SetReadDeadline(t time.Time) error {\n\treturn c.pktConn.SetReadDeadline(t)\n}\n\n// SetWriteDeadline sets the deadline for future Write calls\n// and any currently-blocked Write call.\n// Even if write times out, it may return n > 0, indicating that\n// some of the data was successfully written.\n// A zero value for t means Write will not time out.\nfunc (c *Conn) SetWriteDeadline(t time.Time) error {\n\treturn c.pktConn.SetWriteDeadline(t)\n}\n\n// AddHandler adds a message handler to Conn.\n//\n// By adding HandlerFunc, Conn(and Session, Bearer created over the Conn) will handle\n// the specified type of message with it's paired HandlerFunc when receiving.\n// Messages without registered handlers are just ignored and logged.\n//\n// This should be performed just after creating Conn, otherwise the user cannot retrieve\n// any values, which is in most cases vital to continue working as a node, from the incoming\n// message.\n//\n// The error returned from handler is just logged. Any important due should be done inside\n// the HandlerFunc before returning. This behavior might change in the future.\n//\n// HandlerFunc for EchoResponse and VersionNotSupportedIndication are registered by default.\n// These HandlerFunc can be overridden by specifying message.MsgTypeEchoResponse and/or\n// message.MsgTypeVersionNotSupportedIndication as msgType parameter.\nfunc (c *Conn) AddHandler(msgType uint8, fn HandlerFunc) {\n\tc.msgHandlerMap.store(msgType, fn)\n}\n\n// AddHandlers adds multiple handler funcs at a time, using a map.\n// The key of the map is message type of the GTPv2-C message. You can use MsgTypeFooBar\n// constants defined in this package as well as any raw uint8 values.\n//\n// See AddHandler for how the given handlers behave.\nfunc (c *Conn) AddHandlers(funcs map[uint8]HandlerFunc) {\n\tfor msgType, fn := range funcs {\n\t\tc.msgHandlerMap.store(msgType, fn)\n\t}\n}\n\nfunc (c *Conn) handleMessage(senderAddr net.Addr, msg message.Message) error {\n\tif c.validationEnabled {\n\t\tif err := c.validate(senderAddr, msg); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to validate %s: %w\", msg.MessageTypeName(), err)\n\t\t}\n\t}\n\n\thandle, ok := c.msgHandlerMap.load(msg.MessageType())\n\tif !ok {\n\t\treturn &HandlerNotFoundError{MsgType: msg.MessageTypeName()}\n\t}\n\n\tif err := handle(c, senderAddr, msg); err != nil {\n\t\treturn fmt.Errorf(\"failed to handle %s: %w\", msg.MessageTypeName(), err)\n\t}\n\n\treturn nil\n}\n\n// EnableValidation turns on automatic validation of incoming message.\n// This is expected to be used only after DisableValidation() is used, as the validation\n// is enabled by default.\n//\n// Conn checks if;\n//\n// GTP Version is 2\n// TEID is known to Conn\n//\n// Even the validation is failed, it does not return error to user. Instead, it just logs\n// and discards the packets so that the HandlerFunc won't get the invalid message.\n// Extra validations should be done in HandlerFunc.\nfunc (c *Conn) EnableValidation() {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.validationEnabled = true\n}\n\n// DisableValidation turns off automatic validation of incoming message.\n// It is not recommended to use this except the node is in debugging mode.\n//\n// See EnableValidation for what are validated.\nfunc (c *Conn) DisableValidation() {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.validationEnabled = false\n}\n\nfunc (c *Conn) validate(senderAddr net.Addr, msg message.Message) error {\n\t// check GTP version\n\tif msg.Version() != 2 {\n\t\tif err := c.VersionNotSupportedIndication(senderAddr, msg); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to respond with VersionNotSupportedIndication: %w\", err)\n\t\t}\n\t\treturn fmt.Errorf(\"received an invalid version(%d) of message: %v\", msg.Version(), msg)\n\t}\n\n\t// check if TEID is known or not\n\tif teid := msg.TEID(); teid != 0 {\n\t\tif _, err := c.GetSessionByTEID(teid, senderAddr); err != nil {\n\t\t\treturn &InvalidTEIDError{TEID: teid}\n\t\t}\n\t}\n\treturn nil\n}\n\n// SendMessageTo sends a message to addr.\n// Unlike WriteTo, it sets the Sequence Number properly and returns the one used in the message.\nfunc (c *Conn) SendMessageTo(msg message.Message, addr net.Addr) (uint32, error) {\n\tseq := c.IncSequence()\n\tmsg.SetSequenceNumber(seq)\n\n\tpayload, err := message.Marshal(msg)\n\tif err != nil {\n\t\tseq = c.DecSequence()\n\t\treturn seq, fmt.Errorf(\"failed to send %T: %w\", msg, err)\n\t}\n\n\tif _, err := c.WriteTo(payload, addr); err != nil {\n\t\tseq = c.DecSequence()\n\t\treturn seq, fmt.Errorf(\"failed to send %T: %w\", msg, err)\n\t}\n\treturn seq, nil\n}\n\n// IncSequence increments the SequenceNumber associated with Conn.\nfunc (c *Conn) IncSequence() uint32 {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.sequence++\n\n\t// SequenceNumber is 3-octet long\n\tif c.sequence > 0x7fffff {\n\t\tc.sequence = 0\n\t}\n\n\treturn c.sequence\n}\n\n// DecSequence decrements the SequenceNumber associated with Conn.\nfunc (c *Conn) DecSequence() uint32 {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\tc.sequence--\n\n\treturn c.sequence\n}\n\n// SequenceNumber returns the current(=last used) SequenceNumber associated with Conn.\nfunc (c *Conn) SequenceNumber() uint32 {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\treturn c.sequence\n}\n\n// EchoRequest sends a EchoRequest.\nfunc (c *Conn) EchoRequest(raddr net.Addr) (uint32, error) {\n\tmsg := message.NewEchoRequest(0, ie.NewRecovery(c.RestartCounter))\n\n\tseq, err := c.SendMessageTo(msg, raddr)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn seq, nil\n}\n\n// EchoResponse sends a EchoResponse in response to the EchoRequest.\nfunc (c *Conn) EchoResponse(raddr net.Addr, req message.Message) error {\n\tres := message.NewEchoResponse(0, ie.NewRecovery(c.RestartCounter))\n\n\tif err := c.RespondTo(raddr, req, res); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// VersionNotSupportedIndication sends VersionNotSupportedIndication message\n// in response to any kind of message.Message.\nfunc (c *Conn) VersionNotSupportedIndication(raddr net.Addr, req message.Message) error {\n\tres := message.NewVersionNotSupportedIndication(0, req.Sequence())\n\n\tif err := c.RespondTo(raddr, req, res); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// ParseCreateSession iterates through the ie and returns a session\nfunc (c *Conn) ParseCreateSession(raddr net.Addr, ies ...*ie.IE) (*Session, error) {\n\t// retrieve values from IEs given.\n\tsess := NewSession(raddr, &Subscriber{Location: &Location{}})\n\tbr := sess.GetDefaultBearer()\n\tvar err error\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tsess.IMSI, err = i.IMSI()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase ie.MSISDN:\n\t\t\tsess.MSISDN, err = i.MSISDN()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tsess.IMEI, err = i.MobileEquipmentIdentity()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase ie.ServingNetwork:\n\t\t\tsess.MCC, err = i.MCC()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsess.MNC, err = i.MNC()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase ie.AccessPointName:\n\t\t\tbr.APN, err = i.AccessPointName()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase ie.RATType:\n\t\t\tsess.RATType, err = i.RATType()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tit, err := i.InterfaceType()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tteid, err := i.TEID()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsess.AddTEID(it, teid)\n\t\t\tif it == c.localIfType {\n\t\t\t\tc.RegisterSession(teid, sess)\n\t\t\t}\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tfor _, child := range i.ChildIEs {\n\t\t\t\t\tswitch child.Type {\n\t\t\t\t\tcase ie.EPSBearerID:\n\t\t\t\t\t\tbr.EBI, err = child.EPSBearerID()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\tcase ie.BearerQoS:\n\t\t\t\t\t\tbr.PL, err = child.PriorityLevel()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbr.QCI, err = child.QCILabel()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbr.PCI = child.HasPCI()\n\t\t\t\t\t\tbr.PVI = child.HasPVI()\n\n\t\t\t\t\t\tbr.MBRUL, err = child.MBRForUplink()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbr.MBRDL, err = child.MBRForDownlink()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbr.GBRUL, err = child.GBRForUplink()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbr.GBRDL, err = child.GBRForUplink()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\tcase ie.FullyQualifiedTEID:\n\t\t\t\t\t\tit, err := child.InterfaceType()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tteid, err := child.TEID()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsess.AddTEID(it, teid)\n\t\t\t\t\tcase ie.BearerTFT:\n\t\t\t\t\t\t// XXX - do nothing for BearerTFT?\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase 1:\n\t\t\t\t// XXX - do nothing for BearerContextsToBeRemoved?\n\t\t\t}\n\t\t}\n\t}\n\treturn sess, nil\n}\n\n// CreateSession sends a CreateSessionRequest and stores information given with IE\n// in the Session returned.\n//\n// After using this method, users don't need to call AddSession with the session\n// returned.\n//\n// By creating a Session with this method, the values in IEs given, such as TEID in F-TEID\n// are stored with \"best effort\". See the source code to see what kind information is\n// handled automatically in this method.\n//\n// Also, a Bearer named \"default\" is also created to be used as default bearer.\n// The default bearer can be retrieved by using GetDefaultBearer() or LookupBearerByName(\"default\").\n//\n// Note that this method doesn't care IEs given are sufficient or not, as the required IE\n// varies much depending on the context in which the Create Session Request is used.\n// In other words, any kind of IE can be put on the Create Session Request message using\n// this method.\nfunc (c *Conn) CreateSession(raddr net.Addr, ie ...*ie.IE) (*Session, uint32, error) {\n\n\tsess, err := c.ParseCreateSession(raddr, ie...)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\n\t// set IEs into CreateSessionRequest.\n\tmsg := message.NewCreateSessionRequest(0, 0, ie...)\n\n\tseq, err := c.SendMessageTo(msg, raddr)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\treturn sess, seq, nil\n}\n\n// DeleteSession sends a DeleteSessionRequest with TEID and IEs given.\nfunc (c *Conn) DeleteSession(teid uint32, sess *Session, ie ...*ie.IE) (uint32, error) {\n\tmsg := message.NewDeleteSessionRequest(teid, 0, ie...)\n\n\tseq, err := c.SendMessageTo(msg, sess.peerAddr)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn seq, nil\n}\n\n// ModifyBearer sends a ModifyBearerRequest with TEID and IEs given..\nfunc (c *Conn) ModifyBearer(teid uint32, sess *Session, ie ...*ie.IE) (uint32, error) {\n\tmsg := message.NewModifyBearerRequest(teid, 0, ie...)\n\n\tseq, err := c.SendMessageTo(msg, sess.peerAddr)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn seq, nil\n}\n\n// DeleteBearer sends a DeleteBearerRequest TEID and with IEs given.\nfunc (c *Conn) DeleteBearer(teid uint32, sess *Session, ie ...*ie.IE) (uint32, error) {\n\tmsg := message.NewDeleteBearerRequest(teid, 0, ie...)\n\n\tseq, err := c.SendMessageTo(msg, sess.peerAddr)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn seq, nil\n}\n\n// RespondTo sends a message(specified with \"toBeSent\" param) in response to a message\n// (specified with \"received\" param).\n//\n// This exists to make it easier to handle SequenceNumber.\nfunc (c *Conn) RespondTo(raddr net.Addr, received, toBeSent message.Message) error {\n\ttoBeSent.SetSequenceNumber(received.Sequence())\n\tb := make([]byte, toBeSent.MarshalLen())\n\n\tif err := toBeSent.MarshalTo(b); err != nil {\n\t\treturn err\n\t}\n\n\tif _, err := c.WriteTo(b, raddr); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// GetSessionByTEID returns Session looked up by TEID and sender of the message.\nfunc (c *Conn) GetSessionByTEID(teid uint32, peer net.Addr) (*Session, error) {\n\tsession, ok := c.iteiSessionMap.load(teid)\n\tif !ok {\n\t\treturn nil, &InvalidTEIDError{TEID: teid}\n\t}\n\tif peer.String() != session.peerAddrString {\n\t\treturn nil, &InvalidTEIDError{TEID: teid}\n\t}\n\treturn session, nil\n}\n\n// GetSessionByIMSI returns Session looked up by IMSI.\nfunc (c *Conn) GetSessionByIMSI(imsi string) (*Session, error) {\n\tif session, ok := c.imsiSessionMap.load(imsi); ok {\n\t\treturn session, nil\n\t}\n\treturn nil, &UnknownIMSIError{IMSI: imsi}\n}\n\n// GetIMSIByTEID returns IMSI associated with TEID and the peer node.\nfunc (c *Conn) GetIMSIByTEID(teid uint32, peer net.Addr) (string, error) {\n\tsess, err := c.GetSessionByTEID(teid, peer)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn sess.IMSI, nil\n}\n\n// RegisterSession registers session to Conn with its incoming TEID to\n// distinguish which session the incoming message are for.\n//\n// Incoming TEID(itei) should be the one with it's local interface type.\n// e.g., if the Conn is used for S-GW on S11 I/F, itei should be the one\n// with interface type=IFTypeS11S4SGWGTPC.\nfunc (c *Conn) RegisterSession(itei uint32, session *Session) {\n\tc.iteiSessionMap.store(itei, session)\n\tc.imsiSessionMap.store(session.IMSI, session)\n\n\tsession.AddTEID(c.localIfType, itei)\n}\n\n// RemoveSession removes a session registered in a Conn.\nfunc (c *Conn) RemoveSession(session *Session) {\n\tc.imsiSessionMap.delete(session.IMSI)\n\n\titei, err := session.GetTEID(c.localIfType)\n\tif err != nil { // if incoming TEID could not be found for some reason\n\t\tlogf(\"failed to find incoming TEID in session: %+v\", err)\n\n\t\tc.iteiSessionMap.rangeWithFunc(func(k, v interface{}) bool {\n\t\t\ts := v.(*Session)\n\t\t\tif s.IMSI == session.IMSI {\n\t\t\t\tc.iteiSessionMap.delete(k.(uint32))\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\n\t\treturn\n\t}\n\tc.iteiSessionMap.delete(itei)\n}\n\n// RemoveSessionByIMSI removes a session looked up by IMSI.\n//\n// Use RemoveSession instead if you already have the Session in your hand.\nfunc (c *Conn) RemoveSessionByIMSI(imsi string) {\n\tsess, ok := c.imsiSessionMap.load(imsi)\n\tif !ok {\n\t\tlogf(\"Session not found by IMSI: %s\", imsi)\n\t\treturn\n\t}\n\tc.RemoveSession(sess)\n}\n\n// NewSenderFTEID creates a new F-TEID with random TEID value that is unique within Conn.\n// To ensure the uniqueness, don't create in the other way if you once use this method.\n// This is meant to be used for creating F-TEID IE only for local interface type that is\n// specified at the creation of Conn.\n//\n// Note that in the case there's a lot of Session on the Conn, it may take a long\n// time to find a new unique value.\n//\n// TODO: optimize performance...\nfunc (c *Conn) NewSenderFTEID(v4, v6 string) (fteidIE *ie.IE) {\n\tvar teid uint32\n\tfor try := uint32(0); try < 0xffff; try++ {\n\t\tconst logEvery = 0xff\n\t\tif try&logEvery == logEvery {\n\t\t\tlogf(\"Generating NewSenderFTEID crossed tries:%d\", try)\n\t\t}\n\n\t\tt := generateRandomUint32()\n\t\tif t == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Try to mark TEID as taken. Fails if something exists\n\t\tif ok := c.iteiSessionMap.tryStore(t, nil); !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tteid = t\n\t\tbreak\n\t}\n\n\tif teid == 0 {\n\t\treturn nil\n\t}\n\treturn ie.NewFullyQualifiedTEID(c.localIfType, teid, v4, v6)\n}\n\nfunc generateRandomUint32() uint32 {\n\tb := make([]byte, 4)\n\tif _, err := rand.Read(b); err != nil {\n\t\treturn 0\n\t}\n\n\treturn binary.BigEndian.Uint32(b)\n}\n\n// Sessions returns all the sessions registered in Conn.\nfunc (c *Conn) Sessions() []*Session {\n\tvar ss []*Session\n\tc.imsiSessionMap.rangeWithFunc(func(k, v interface{}) bool {\n\t\tss = append(ss, v.(*Session))\n\t\treturn true\n\t})\n\n\treturn ss\n}\n\n// SessionCount returns the number of sessions registered in Conn.\n//\n// This may have some impact on performance in case of large number of Session exists.\nfunc (c *Conn) SessionCount() int {\n\tvar count int\n\tc.imsiSessionMap.rangeWithFunc(func(k, v interface{}) bool {\n\t\tsess := v.(*Session)\n\t\tif sess.IsActive() {\n\t\t\tcount++\n\t\t}\n\t\treturn true\n\t})\n\n\treturn count\n}\n\n// BearerCount returns the number of bearers registered in Conn.\n//\n// This may have some impact on performance in case of large number of Session and Bearer exist.\nfunc (c *Conn) BearerCount() int {\n\tvar count int\n\tc.imsiSessionMap.rangeWithFunc(func(k, v interface{}) bool {\n\t\tsess := v.(*Session)\n\t\tif sess.IsActive() {\n\t\t\tcount += sess.BearerCount()\n\t\t}\n\t\treturn true\n\t})\n\n\treturn count\n}\n\ntype imsiSessionMap struct {\n\tsyncMap sync.Map\n}\n\nfunc newimsiSessionMap() *imsiSessionMap {\n\treturn &imsiSessionMap{}\n}\n\nfunc (i *imsiSessionMap) store(imsi string, session *Session) {\n\ti.syncMap.Store(imsi, session)\n}\n\nfunc (i *imsiSessionMap) load(imsi string) (*Session, bool) {\n\tsession, ok := i.syncMap.Load(imsi)\n\tif ok && session != nil {\n\t\treturn session.(*Session), true\n\t}\n\treturn nil, ok\n}\n\nfunc (i *imsiSessionMap) delete(imsi string) {\n\ti.syncMap.Delete(imsi)\n}\n\nfunc (i *imsiSessionMap) rangeWithFunc(fn func(imsi, session interface{}) bool) {\n\ti.syncMap.Range(fn)\n}\n\ntype iteiSessionMap struct {\n\tsyncMap sync.Map\n}\n\nfunc newiteiSessionMap() *iteiSessionMap {\n\treturn &iteiSessionMap{}\n}\n\nfunc (t *iteiSessionMap) store(teid uint32, session *Session) {\n\tt.syncMap.Store(teid, session)\n}\n\nfunc (t *iteiSessionMap) tryStore(teid uint32, session *Session) bool {\n\t_, loaded := t.syncMap.LoadOrStore(teid, session)\n\treturn !loaded\n}\n\nfunc (t *iteiSessionMap) load(teid uint32) (*Session, bool) {\n\tsession, ok := t.syncMap.Load(teid)\n\tif ok && session != nil {\n\t\treturn session.(*Session), true\n\t}\n\treturn nil, ok\n}\n\nfunc (t *iteiSessionMap) delete(teid uint32) {\n\tt.syncMap.Delete(teid)\n}\n\nfunc (t *iteiSessionMap) rangeWithFunc(fn func(imsi, session interface{}) bool) {\n\tt.syncMap.Range(fn)\n}\n"
  },
  {
    "path": "gtpv2/conn_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc setup(ctx context.Context, doneCh chan struct{}) (cliConn, srvConn *gtpv2.Conn, err error) {\n\tcliAddr, err := net.ResolveUDPAddr(\"udp\", \"127.0.0.1\"+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tsrvAddr, err := net.ResolveUDPAddr(\"udp\", \"127.0.0.2\"+gtpv2.GTPCPort)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tsrvCreated := make(chan struct{})\n\tgo func() {\n\t\tsrvConn = gtpv2.NewConn(srvAddr, gtpv2.IFTypeS11S4SGWGTPC, 0)\n\t\tsrvConn.AddHandler(\n\t\t\tmessage.MsgTypeCreateSessionRequest,\n\t\t\tfunc(c *gtpv2.Conn, cliAddr net.Addr, msg message.Message) error {\n\n\t\t\t\tcsReq := msg.(*message.CreateSessionRequest)\n\t\t\t\tsession := gtpv2.NewSession(cliAddr, &gtpv2.Subscriber{Location: &gtpv2.Location{}})\n\n\t\t\t\tvar otei uint32\n\t\t\t\tif imsiIE := csReq.IMSI; imsiIE != nil {\n\t\t\t\t\timsi, err := imsiIE.IMSI()\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tif imsi != \"123451234567890\" {\n\t\t\t\t\t\treturn fmt.Errorf(\"unexpected IMSI: %s\", imsi)\n\t\t\t\t\t}\n\t\t\t\t\tsession.IMSI = imsi\n\t\t\t\t} else {\n\t\t\t\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.IMSI}\n\t\t\t\t}\n\n\t\t\t\tif fteidcIE := csReq.SenderFTEIDC; fteidcIE != nil {\n\t\t\t\t\tip, err := fteidcIE.IPAddress()\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tif ip != \"127.0.0.1\" {\n\t\t\t\t\t\treturn fmt.Errorf(\"unexpected IP in F-TEID: %s\", ip)\n\t\t\t\t\t}\n\n\t\t\t\t\tifType, err := fteidcIE.InterfaceType()\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\totei, err = fteidcIE.TEID()\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tsession.AddTEID(ifType, otei)\n\t\t\t\t} else {\n\t\t\t\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.IMSI}\n\t\t\t\t}\n\n\t\t\t\tfTEID := srvConn.NewSenderFTEID(\"127.0.0.2\", \"\")\n\t\t\t\tsrvConn.RegisterSession(fTEID.MustTEID(), session)\n\t\t\t\tcsRsp := message.NewCreateSessionResponse(\n\t\t\t\t\totei, msg.Sequence(), ie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil), fTEID,\n\t\t\t\t)\n\t\t\t\tif err := c.RespondTo(cliAddr, csReq, csRsp); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tif err := session.Activate(); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdoneCh <- struct{}{}\n\t\t\t\treturn nil\n\t\t\t},\n\t\t)\n\n\t\tif err := srvConn.Listen(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t\tsrvCreated <- struct{}{}\n\t\tif err := srvConn.Serve(ctx); err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn\n\t\t}\n\t}()\n\n\tselect {\n\tcase <-srvCreated:\n\tcase <-time.After(2 * time.Second):\n\t\tfmt.Println(\"Timeout waiting for server creation\")\n\t}\n\tcliConn, err = gtpv2.Dial(ctx, cliAddr, srvAddr, gtpv2.IFTypeS11MMEGTPC, 0)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn cliConn, srvConn, nil\n}\n\nfunc TestCreateSession(t *testing.T) {\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tdoneCh := make(chan struct{})\n\trspOK := make(chan struct{})\n\n\tcliConn, srvConn, err := setup(ctx, doneCh)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcliConn.AddHandler(\n\t\tmessage.MsgTypeCreateSessionResponse,\n\t\tfunc(c *gtpv2.Conn, srvAddr net.Addr, msg message.Message) error {\n\t\t\tif srvAddr.String() != \"127.0.0.2\"+gtpv2.GTPCPort {\n\t\t\t\tt.Errorf(\"invalid server address: %s\", srvAddr)\n\t\t\t}\n\t\t\tif msg.Sequence() != cliConn.SequenceNumber() {\n\t\t\t\tt.Errorf(\"invalid sequence number. got: %d, want: %d\", msg.Sequence(), cliConn.SequenceNumber())\n\t\t\t}\n\n\t\t\tsession, err := c.GetSessionByTEID(msg.TEID(), srvAddr)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcsRsp := msg.(*message.CreateSessionResponse)\n\t\t\tif causeIE := csRsp.Cause; causeIE != nil {\n\t\t\t\tcause, err := causeIE.Cause()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif cause != gtpv2.CauseRequestAccepted {\n\t\t\t\t\treturn &gtpv2.CauseNotOKError{\n\t\t\t\t\t\tMsgType: csRsp.MessageTypeName(),\n\t\t\t\t\t\tCause:   cause,\n\t\t\t\t\t\tMsg:     \"something went wrong\",\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.Cause}\n\t\t\t}\n\n\t\t\tif fteidIE := csRsp.SenderFTEIDC; fteidIE != nil {\n\t\t\t\tit, err := fteidIE.InterfaceType()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif it != gtpv2.IFTypeS11S4SGWGTPC {\n\t\t\t\t\treturn fmt.Errorf(\"invalid InterfaceType: %v\", it)\n\t\t\t\t}\n\t\t\t\totei, err := fteidIE.TEID()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tsession.AddTEID(it, otei)\n\n\t\t\t\tip, err := fteidIE.IPAddress()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif ip != \"127.0.0.2\" {\n\t\t\t\t\treturn fmt.Errorf(\"unexpected IP in F-TEID: %s\", ip)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn &gtpv2.RequiredIEMissingError{Type: ie.Cause}\n\t\t\t}\n\n\t\t\tif err := session.Activate(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\trspOK <- struct{}{}\n\t\t\treturn nil\n\t\t},\n\t)\n\n\tfTEID := cliConn.NewSenderFTEID(\"127.0.0.1\", \"\")\n\t_, _, err = cliConn.CreateSession(srvConn.LocalAddr(), ie.NewIMSI(\"123451234567890\"), fTEID)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tselect {\n\tcase <-rspOK:\n\t\tif count := cliConn.SessionCount(); count != 1 {\n\t\t\tt.Errorf(\"wrong SessionCount in cliConn. want %d, got: %d\", 1, count)\n\t\t}\n\t\tif count := cliConn.BearerCount(); count != 1 {\n\t\t\tt.Errorf(\"wrong BearerCount in cliConn. want %d, got: %d\", 1, count)\n\t\t}\n\n\t\t<-doneCh\n\t\tif count := srvConn.SessionCount(); count != 1 {\n\t\t\tt.Errorf(\"wrong SessionCount in srvConn. want %d, got: %d\", 1, count)\n\t\t}\n\t\tif count := srvConn.BearerCount(); count != 1 {\n\t\t\tt.Errorf(\"wrong BearerCount in srvConn. want %d, got: %d\", 1, count)\n\t\t}\n\tcase <-time.After(5 * time.Second):\n\t\tt.Fatal(\"timed out while waiting for validating Create Session Response\")\n\t}\n}\n"
  },
  {
    "path": "gtpv2/constants.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\n// Fixes for the constants with wrong names (original ones are kept for compatibility).\nconst (\n\tContIDMSSupportOfNetworkRequestedBearerControlIndicator uint16 = 5  // ContIDMSSupportofNetworkRequestedBearerControlIndicator\n\tContIDIPAddressAllocationViaNASSignalling               uint16 = 10 // ContIDIPaddressAllocationViaNASSignalling\n\tContIDIPv4AddressAllocationViaDHCPv4                    uint16 = 11 // ContIDIPv4addressAllocationViaDHCPv4\n\tContID3GPPPSDataOffUEStatus                             uint16 = 23 // ContID3GPPPSDataOffUEstatus\n\n\tSelectionModeMSOrNetworkProvidedAPNSubscribedVerified uint8 = 0 // SelectionModeMSorNetworkProvidedAPNSubscribedVerified\n)\n\n// Registered UDP ports\nconst (\n\tGTPCPort = \":2123\"\n\tGTPUPort = \":2152\"\n)\n\n// InterfaceType definitions.\nconst (\n\tIFTypeS1UeNodeBGTPU uint8 = iota\n\tIFTypeS1USGWGTPU\n\tIFTypeS12RNCGTPU\n\tIFTypeS12SGWGTPU\n\tIFTypeS5S8SGWGTPU\n\tIFTypeS5S8PGWGTPU\n\tIFTypeS5S8SGWGTPC\n\tIFTypeS5S8PGWGTPC\n\tIFTypeS5S8SGWPMIPv6\n\tIFTypeS5S8PGWPMIPv6\n\tIFTypeS11MMEGTPC\n\tIFTypeS11S4SGWGTPC\n\tIFTypeS10MMEGTPC\n\tIFTypeS3MMEGTPC\n\tIFTypeS3SGSNGTPC\n\tIFTypeS4SGSNGTPU\n\tIFTypeS4SGWGTPU\n\tIFTypeS4SGSNGTPC\n\tIFTypeS16SGSNGTPC\n\tIFTypeeNodeBGTPUForDL\n\tIFTypeeNodeBGTPUForUL\n\tIFTypeRNCGTPUForData\n\tIFTypeSGSNGTPUForData\n\tIFTypeSGWUPFGTPUForDL\n\tIFTypeSmMBMSGWGTPC\n\tIFTypeSnMBMSGWGTPC\n\tIFTypeSmMMEGTPC\n\tIFTypeSnSGSNGTPC\n\tIFTypeSGWGTPUForUL\n\tIFTypeSnSGSNGTPU\n\tIFTypeS2bePDGGTPC\n\tIFTypeS2bUePDGGTPU\n\tIFTypeS2bPGWGTPC\n\tIFTypeS2bUPGWGTPU\n\tIFTypeS2aTWANGTPU\n\tIFTypeS2aTWANGTPC\n\tIFTypeS2aPGWGTPC\n\tIFTypeS2aPGWGTPU\n\tIFTypeS11MMEGTPU\n\tIFTypeS11SGWGTPU\n)\n\n// APN Restriction definitions.\nconst (\n\tAPNRestrictionNoExistingContextsorRestriction uint8 = iota\n\tAPNRestrictionPublic1\n\tAPNRestrictionPublic2\n\tAPNRestrictionPrivate1\n\tAPNRestrictionPrivate2\n)\n\n// Cause definitions.\nconst (\n\t_                                                                                   uint8 = 0\n\t_                                                                                   uint8 = 1\n\tCauseLocalDetach                                                                    uint8 = 2\n\tCauseCompleteDetach                                                                 uint8 = 3\n\tCauseRATChangedFrom3GPPToNon3GPP                                                    uint8 = 4\n\tCauseISRDeactivation                                                                uint8 = 5\n\tCauseErrorIndicationReceivedFromRNCeNodeBS4SGSNMME                                  uint8 = 6\n\tCauseIMSIDetachOnly                                                                 uint8 = 7\n\tCauseReactivationRequested                                                          uint8 = 8\n\tCausePDNReconnectionToThisAPNDisallowed                                             uint8 = 9\n\tCauseAccessChangedFromNon3GPPTo3GPP                                                 uint8 = 10\n\tCausePDNConnectionInactivityTimerExpires                                            uint8 = 11\n\tCausePGWNotResponding                                                               uint8 = 12\n\tCauseNetworkFailure                                                                 uint8 = 13\n\tCauseQoSParameterMismatch                                                           uint8 = 14\n\t_                                                                                   uint8 = 15\n\tCauseRequestAccepted                                                                uint8 = 16\n\tCauseRequestAcceptedPartially                                                       uint8 = 17\n\tCauseNewPDNTypeDueToNetworkPreference                                               uint8 = 18\n\tCauseNewPDNTypeDueToSingleAddressBearerOnly                                         uint8 = 19\n\tCauseContextNotFound                                                                uint8 = 64\n\tCauseInvalidMessageFormat                                                           uint8 = 65\n\tCauseVersionNotSupportedByNextPeer                                                  uint8 = 66\n\tCauseInvalidLength                                                                  uint8 = 67\n\tCauseServiceNotSupported                                                            uint8 = 68\n\tCauseMandatoryIEIncorrect                                                           uint8 = 69\n\tCauseMandatoryIEMissing                                                             uint8 = 70\n\t_                                                                                   uint8 = 71\n\tCauseSystemFailure                                                                  uint8 = 72\n\tCauseNoResourcesAvailable                                                           uint8 = 73\n\tCauseSemanticErrorInTheTFTOperation                                                 uint8 = 74\n\tCauseSyntacticErrorInTheTFTOperation                                                uint8 = 75\n\tCauseSemanticErrorsInPacketFilters                                                  uint8 = 76\n\tCauseSyntacticErrorsInPacketFilters                                                 uint8 = 77\n\tCauseMissingOrUnknownAPN                                                            uint8 = 78\n\t_                                                                                   uint8 = 79\n\tCauseGREKeyNotFound                                                                 uint8 = 80\n\tCauseRelocationFailure                                                              uint8 = 81\n\tCauseDeniedInRAT                                                                    uint8 = 82\n\tCausePreferredPDNTypeNotSupported                                                   uint8 = 83\n\tCauseAllDynamicAddressesAreOccupied                                                 uint8 = 84\n\tCauseUEContextWithoutTFTAlreadyActivated                                            uint8 = 85\n\tCauseProtocolTypeNotSupported                                                       uint8 = 86\n\tCauseUENotResponding                                                                uint8 = 87\n\tCauseUERefuses                                                                      uint8 = 88\n\tCauseServiceDenied                                                                  uint8 = 89\n\tCauseUnableToPageUE                                                                 uint8 = 90\n\tCauseNoMemoryAvailable                                                              uint8 = 91\n\tCauseUserAuthenticationFailed                                                       uint8 = 92\n\tCauseAPNAccessDeniedNoSubscription                                                  uint8 = 93\n\tCauseRequestRejectedReasonNotSpecified                                              uint8 = 94\n\tCausePTMSISignatureMismatch                                                         uint8 = 95\n\tCauseIMSIIMEINotKnown                                                               uint8 = 96\n\tCauseSemanticErrorInTheTADOperation                                                 uint8 = 97\n\tCauseSyntacticErrorInTheTADOperation                                                uint8 = 98\n\t_                                                                                   uint8 = 99\n\tCauseRemotePeerNotResponding                                                        uint8 = 100\n\tCauseCollisionWithNetworkInitiatedRequest                                           uint8 = 101\n\tCauseUnableToPageUEDueToSuspension                                                  uint8 = 102\n\tCauseConditionalIEMissing                                                           uint8 = 103\n\tCauseAPNRestrictionTypeIncompatibleWithCurrentlyActivePDNConnection                 uint8 = 104\n\tCauseInvalidOverallLengthOfTheTriggeredResponseMessageAndAPiggybackedInitialMessage uint8 = 105\n\tCauseDataForwardingNotSupported                                                     uint8 = 106\n\tCauseInvalidReplyFromRemotePeer                                                     uint8 = 107\n\tCauseFallbackToGTPv1                                                                uint8 = 108\n\tCauseInvalidPeer                                                                    uint8 = 109\n\tCauseTemporarilyRejectedDueToHandoverTAURAUProcedureInProgress                      uint8 = 110\n\tCauseModificationsNotLimitedToS1UBearers                                            uint8 = 111\n\tCauseRequestRejectedForAPMIPv6Reason                                                uint8 = 112\n\tCauseAPNCongestion                                                                  uint8 = 113\n\tCauseBearerHandlingNotSupported                                                     uint8 = 114\n\tCauseUEAlreadyReattached                                                            uint8 = 115\n\tCauseMultiplePDNConnectionsForAGivenAPNNotAllowed                                   uint8 = 116\n\tCauseTargetAccessRestrictedForTheSubscriber                                         uint8 = 117\n\t_                                                                                   uint8 = 118\n\tCauseMMESGSNRefusesDueToVPLMNPolicy                                                 uint8 = 119\n\tCauseGTPCEntityCongestion                                                           uint8 = 120\n\tCauseLateOverlappingRequest                                                         uint8 = 121\n\tCauseTimedOutRequest                                                                uint8 = 122\n\tCauseUEIsTemporarilyNotReachableDueToPowerSaving                                    uint8 = 123\n\tCauseRelocationFailureDueToNASMessageRedirection                                    uint8 = 124\n\tCauseUENotAuthorisedByOCSOrExternalAAAServer                                        uint8 = 125\n\tCauseMultipleAccessesToAPDNConnectionNotAllowed                                     uint8 = 126\n\tCauseRequestRejectedDueToUECapability                                               uint8 = 127\n\tCauseS1UPathFailure                                                                 uint8 = 128\n)\n\n// CSG Membership Indication definitions.\nconst (\n\tCMINonCSG uint8 = iota\n\tCMICSG\n)\n\n// Detach Type definitions.\nconst (\n\t_ uint8 = iota\n\tDetachTypePS\n\tDetachTypeCombinedPSCS\n)\n\n// Node-ID Type definitions.\nconst (\n\tNodeIDIPv4 uint8 = iota\n\tNodeIDIPv6\n\tNodeIDOther\n)\n\n// Node Type definitions.\nconst (\n\tNodeTypeSGSN uint8 = iota\n\tNodeTypeMME\n)\n\n// Protocol ID definitions.\n// For more identifiers, see RFC 3232.\nconst (\n\tProtoIDLCP  uint16 = 0xc021\n\tProtoIDPAP  uint16 = 0xc023\n\tProtoIDCHAP uint16 = 0xc223\n\tProtoIDIPCP uint16 = 0x8021\n)\n\n// Container ID definitions.\nconst (\n\t_ uint16 = iota\n\tContIDPCSCFIPv6AddressRequest\n\tContIDIMCNSubsystemSignalingFlag\n\tContIDDNSServerIPv6AddressRequest\n\tContIDNotSupported\n\tContIDMSSupportofNetworkRequestedBearerControlIndicator\n\t_\n\tContIDDSMIPv6HomeAgentAddressRequest\n\tContIDDSMIPv6HomeNetworkPrefixRequest\n\tContIDDSMIPv6IPv4HomeAgentAddressRequest\n\tContIDIPaddressAllocationViaNASSignalling\n\tContIDIPv4addressAllocationViaDHCPv4\n\tContIDPCSCFIPv4AddressRequest\n\tContIDDNSServerIPv4AddressRequest\n\tContIDMSISDNRequest\n\tContIDIFOMSupportRequest\n\tContIDIPv4LinkMTURequest\n\tContIDMSSupportOfLocalAddressInTFTIndicator\n\tContIDPCSCFReselectionSupport\n\tContIDNBIFOMRequestIndicator\n\tContIDNBIFOMMode\n\tContIDNonIPLinkMTURequest\n\tContIDAPNRateControlSupportIndicator\n\tContID3GPPPSDataOffUEstatus\n\tContIDReliableDataServiceRequestIndicator\n\tContIDAdditionalAPNRateControlForExceptionDataSupportIndicator\n\tContIDPDUSessionID\n\t_\n\t_\n\t_\n\t_\n\t_\n\tContIDEthernetFramePayloadMTURequest\n\tContIDUnstructuredLinkMTURequest\n\tContID5GSMCauseValue\n)\n\n// Configuration Protocol definitions.\nconst (\n\tConfigProtocolPPPWithIP uint8 = 0\n)\n\n// PDN Type definitions.\nconst (\n\t_ uint8 = iota\n\tPDNTypeIPv4\n\tPDNTypeIPv6\n\tPDNTypeIPv4v6\n\tPDNTypeNonIP\n)\n\n// Protocol Type definitions.\nconst (\n\t_ uint8 = iota\n\tProtoTypeS1APCause\n\tProtoTypeEMMCause\n\tProtoTypeESMCause\n\tProtoTypeDiameterCause\n\tProtoTypeIKEv2Cause\n)\n\n// Cause Type definitions.\nconst (\n\tCauseTypeRadioNetworkLayer uint8 = iota\n\tCauseTypeTransportLayer\n\tCauseTypeNAS\n\tCauseTypeProtocol\n\tCauseTypeMiscellaneous\n)\n\n// RAT Type definitions.\nconst (\n\t_ uint8 = iota\n\tRATTypeUTRAN\n\tRATTypeGERAN\n\tRATTypeWLAN\n\tRATTypeGAN\n\tRATTypeHSPAEvolution\n\tRATTypeEUTRAN\n\tRATTypeVirtual\n\tRATTypeEUTRANNBIoT\n\tRATTypeLTEM\n\tRATTypeNR\n)\n\n// SelectionMode definitions.\nconst (\n\tSelectionModeMSorNetworkProvidedAPNSubscribedVerified uint8 = iota\n\tSelectionModeMSProvidedAPNSubscriptionNotVerified\n\tSelectionModeNetworkProvidedAPNSubscriptionNotVerified\n)\n\n// Service Indicator definitions.\nconst (\n\t_ uint8 = iota\n\tServiceIndCSCall\n\tServiceIndSMS\n)\n\n// Access Mode definitions.\nconst (\n\tAccessModeClosed uint8 = iota\n\tAccessModeHybrid\n)\n\n// Daylight Saving Time definitions.\nconst (\n\tDaylightSavingNoAdjustment uint8 = iota\n\tDaylightSavingPlusOneHour\n\tDaylightSavingPlusTwoHours\n)\n"
  },
  {
    "path": "gtpv2/doc.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package gtpv2 provides the simple and painless handling of GTPv2-C protocol in pure Golang.\n//\n// Please see README.md for detailed usage of the APIs provided by this package.\n//\n// https://github.com/wmnsk/go-gtp/blob/main/gtpv2/README.md\npackage gtpv2\n"
  },
  {
    "path": "gtpv2/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nvar (\n\t// ErrTEIDNotFound indicates that TEID is not registered for the interface specified.\n\tErrTEIDNotFound = errors.New(\"no TEID found\")\n\n\t// ErrTimeout indicates that a handler failed to complete its work due to the\n\t// absence of message expected to come from another endpoint.\n\tErrTimeout = errors.New(\"timed out\")\n)\n\n// CauseNotOKError indicates that the value in Cause IE is not OK.\ntype CauseNotOKError struct {\n\tMsgType string\n\tCause   uint8\n\tMsg     string\n}\n\n// Error returns error cause with message.\nfunc (e *CauseNotOKError) Error() string {\n\treturn fmt.Sprintf(\"got non-OK Cause: %d in %s; %s\", e.Cause, e.MsgType, e.Msg)\n}\n\n// RequiredIEMissingError indicates that the IE required is missing.\ntype RequiredIEMissingError struct {\n\tType uint8\n}\n\n// Error returns error with missing IE type.\nfunc (e *RequiredIEMissingError) Error() string {\n\treturn fmt.Sprintf(\"required IE missing: %d\", e.Type)\n}\n\n// RequiredParameterMissingError indicates that no Bearer found by lookup methods.\ntype RequiredParameterMissingError struct {\n\tName, Msg string\n}\n\n// Error returns missing parameter with message.\nfunc (e *RequiredParameterMissingError) Error() string {\n\treturn fmt.Sprintf(\"required parameter: %s is missing. %s\", e.Name, e.Msg)\n}\n\n// UnexpectedTypeError indicates that the type of incoming message is not expected.\ntype UnexpectedTypeError struct {\n\tMsg message.Message\n}\n\n// Error returns violating message type.\nfunc (e *UnexpectedTypeError) Error() string {\n\treturn fmt.Sprintf(\"got unexpected type of message: %T\", e.Msg)\n}\n\n// UnexpectedIEError indicates that the type of incoming message is not expected.\ntype UnexpectedIEError struct {\n\tIEType uint8\n}\n\n// Error returns violating message type.\nfunc (e *UnexpectedIEError) Error() string {\n\treturn fmt.Sprintf(\"got unexpected type of message: %T\", e.IEType)\n}\n\n// InvalidVersionError indicates that the version of the message specified by the user\n// is not acceptable for the receiver.\ntype InvalidVersionError struct {\n\tVersion int\n}\n\n// Error returns violationg version.\nfunc (e *InvalidVersionError) Error() string {\n\treturn fmt.Sprintf(\"version: %d is not acceptable for the receiver\", e.Version)\n}\n\n// InvalidSequenceError indicates that the Sequence Number is invalid.\ntype InvalidSequenceError struct {\n\tSeq uint32\n}\n\n// Error returns violating Sequence Number.\nfunc (e *InvalidSequenceError) Error() string {\n\treturn fmt.Sprintf(\"got invalid Sequence Number: %d\", e.Seq)\n}\n\n// InvalidTEIDError indicates that the TEID value is different from expected one or\n// not registered in TEIDMap.\ntype InvalidTEIDError struct {\n\tTEID uint32\n}\n\n// Error returns violating TEID.\nfunc (e *InvalidTEIDError) Error() string {\n\treturn fmt.Sprintf(\"got invalid TEID: %#08x\", e.TEID)\n}\n\n// UnknownIMSIError indicates that the IMSI is different from expected one.\ntype UnknownIMSIError struct {\n\tIMSI string\n}\n\n// Error returns violating IMSI.\nfunc (e *UnknownIMSIError) Error() string {\n\treturn fmt.Sprintf(\"got unknown IMSI: %s\", e.IMSI)\n}\n\n// UnknownAPNError indicates that the APN is different from expected one.\ntype UnknownAPNError struct {\n\tAPN string\n}\n\n// Error returns violating APN.\nfunc (e *UnknownAPNError) Error() string {\n\treturn fmt.Sprintf(\"got unknown APN: %s\", e.APN)\n}\n\n// InvalidSessionError indicates that something went wrong with Session.\ntype InvalidSessionError struct {\n\tIMSI string\n}\n\n// Error returns message with IMSI associated with Session if available.\nfunc (e *InvalidSessionError) Error() string {\n\treturn fmt.Sprintf(\"invalid session, IMSI: %s\", e.IMSI)\n}\n\n// BearerNotFoundError indicates that no Bearer found by lookup methods.\ntype BearerNotFoundError struct {\n\tIMSI string\n}\n\n// Error returns message with IMSI associated with Bearer if available.\nfunc (e *BearerNotFoundError) Error() string {\n\treturn fmt.Sprintf(\"no Bearer found: %s\", e.IMSI)\n}\n\n// HandlerNotFoundError indicates that the handler func is not registered in *Conn\n// for the incoming GTPv2 message. In usual cases this error should not be taken\n// as fatal, as the other endpoint can make your program stop working just by\n// sending unregistered message.\ntype HandlerNotFoundError struct {\n\tMsgType string\n}\n\n// Error returns violating message type to handle.\nfunc (e *HandlerNotFoundError) Error() string {\n\treturn fmt.Sprintf(\"no handlers found for incoming message: %s, ignoring\", e.MsgType)\n}\n"
  },
  {
    "path": "gtpv2/handlers.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\nimport (\n\t\"net\"\n\t\"sync\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// HandlerFunc is a handler for specific GTPv2-C message.\ntype HandlerFunc func(c *Conn, senderAddr net.Addr, msg message.Message) error\n\ntype msgHandlerMap struct {\n\tsyncMap sync.Map\n}\n\nfunc (m *msgHandlerMap) store(msgType uint8, handler HandlerFunc) {\n\tm.syncMap.Store(msgType, handler)\n}\n\nfunc (m *msgHandlerMap) load(msgType uint8) (HandlerFunc, bool) {\n\thandler, ok := m.syncMap.Load(msgType)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\n\treturn handler.(HandlerFunc), true\n}\n\nfunc newMsgHandlerMap(m map[uint8]HandlerFunc) *msgHandlerMap {\n\tmhm := &msgHandlerMap{syncMap: sync.Map{}}\n\tfor k, v := range m {\n\t\tmhm.store(k, v)\n\t}\n\n\treturn mhm\n}\n\nfunc newDefaultMsgHandlerMap() *msgHandlerMap {\n\treturn newMsgHandlerMap(\n\t\tmap[uint8]HandlerFunc{\n\t\t\tmessage.MsgTypeEchoRequest:                   handleEchoRequest,\n\t\t\tmessage.MsgTypeEchoResponse:                  handleEchoResponse,\n\t\t\tmessage.MsgTypeVersionNotSupportedIndication: handleVersionNotSupportedIndication,\n\t\t},\n\t)\n}\n\nfunc handleEchoRequest(c *Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tif _, ok := msg.(*message.EchoRequest); !ok {\n\t\treturn &UnexpectedTypeError{Msg: msg}\n\t}\n\n\t// respond with EchoResponse.\n\treturn c.RespondTo(\n\t\tsenderAddr, msg, message.NewEchoResponse(0, ie.NewRecovery(c.RestartCounter)),\n\t)\n}\n\nfunc handleEchoResponse(c *Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tif _, ok := msg.(*message.EchoResponse); !ok {\n\t\treturn &UnexpectedTypeError{Msg: msg}\n\t}\n\n\t// do nothing.\n\treturn nil\n}\n\nfunc handleVersionNotSupportedIndication(c *Conn, senderAddr net.Addr, msg message.Message) error {\n\t// this should never happen, as the type should have been assured by\n\t// msgHandlerMap before this function is called.\n\tif _, ok := msg.(*message.VersionNotSupportedIndication); !ok {\n\t\treturn &UnexpectedTypeError{Msg: msg}\n\t}\n\n\t// let's just return err anyway.\n\treturn &InvalidVersionError{Version: msg.Version()}\n}\n"
  },
  {
    "path": "gtpv2/helpers_test.go",
    "content": "package gtpv2_test\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"net\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n)\n\nvar testConn *gtpv2.Conn\nvar sessions []*gtpv2.Session\nvar dummyAddr net.Addr = &net.UDPAddr{IP: net.IP{0x00, 0x00, 0x00, 0x00}, Port: 2123}\n\nfunc init() {\n\ttestConn = gtpv2.NewConn(dummyAddr, gtpv2.IFTypeS11MMEGTPC, 0)\n\tsessions = []*gtpv2.Session{\n\t\tgtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567891\"}),\n\t\tgtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567892\"}),\n\t\tgtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567893\"}),\n\t\tgtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567894\"}),\n\t}\n\n\tfor i, sess := range sessions {\n\t\t_ = sess.Activate()\n\t\tsess.AddTEID(gtpv2.IFTypeS11MMEGTPC, uint32(i+1))\n\t\ttestConn.RegisterSession(uint32(i+1), sess)\n\t}\n}\n\nfunc TestSessionCount(t *testing.T) {\n\tif want, got := testConn.SessionCount(), len(sessions); want != got {\n\t\tt.Errorf(\"SessionCount is invalid. want: %d, got: %d\", want, got)\n\t}\n}\n\nfunc TestGetSessionByIMSI_GetTEID(t *testing.T) {\n\tfor i := 1; i <= testConn.SessionCount(); i++ {\n\t\tlastDigit := strconv.Itoa(i)\n\t\tsess, err := testConn.GetSessionByIMSI(\"00101123456789\" + lastDigit)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tteid, err := sess.GetTEID(gtpv2.IFTypeS11MMEGTPC)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tif teid != uint32(i) {\n\t\t\tt.Errorf(\"Got wrong TEID at %d, %d, %s\", i, teid, sess.IMSI)\n\t\t}\n\t}\n}\n\nfunc BenchmarkAddSession(b *testing.B) {\n\tfor k := 0.; k < 6; k++ {\n\t\texistingSessions := int(math.Pow(10, k))\n\t\tbenchConn := gtpv2.NewConn(dummyAddr, gtpv2.IFTypeS11MMEGTPC, 0)\n\t\tfor i := 0; i < existingSessions; i++ {\n\t\t\timsi := fmt.Sprintf(\"%015d\", i)\n\t\t\tbenchConn.RegisterSession(0, gtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: imsi}))\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"%d\", existingSessions), func(b *testing.B) {\n\t\t\tfor i := 1; i <= b.N; i++ {\n\t\t\t\tbenchConn.RegisterSession(0, gtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567891\"}))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestGetSessionByTEID(t *testing.T) {\n\tfor i := 1; i <= testConn.SessionCount(); i++ {\n\t\tsess, err := testConn.GetSessionByTEID(uint32(i), dummyAddr)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tlastDigit := strconv.Itoa(i)\n\t\tif string(sess.IMSI[14]) != lastDigit {\n\t\t\tt.Errorf(\"Got wrong session at %d, %s\", i, sess.IMSI)\n\t\t}\n\t}\n}\n\nfunc TestGetIMSIByTEID(t *testing.T) {\n\tfor i := 1; i <= testConn.SessionCount(); i++ {\n\t\timsi, err := testConn.GetIMSIByTEID(uint32(i), dummyAddr)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tlastDigit := strconv.Itoa(i)\n\t\tif string(imsi[14]) != lastDigit {\n\t\t\tt.Errorf(\"Got wrong IMSI at %d, %s\", i, imsi)\n\t\t}\n\t}\n}\n\nfunc TestRemoveSession(t *testing.T) {\n\ttestConn.RemoveSession(sessions[0])\n\n\tif testConn.SessionCount() != len(sessions)-1 {\n\t\tt.Errorf(\"Session not removed expectedly: %d, %v\", testConn.SessionCount(), testConn.Sessions())\n\t}\n\n\tfor i := 2; i <= testConn.SessionCount(); i++ {\n\t\tsess, err := testConn.GetSessionByTEID(uint32(i), dummyAddr)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tlastDigit := strconv.Itoa(i)\n\t\tif string(sess.IMSI[14]) != lastDigit {\n\t\t\tt.Errorf(\"Got wrong session at %d, %s\", i, sess.IMSI)\n\t\t}\n\t}\n\n\t// add the session again\n\ts := gtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567891\"})\n\t_ = s.Activate()\n\ts.AddTEID(gtpv2.IFTypeS11MMEGTPC, uint32(0))\n\ttestConn.RegisterSession(0, s)\n}\n\nfunc TestRemoveSessionByIMSI(t *testing.T) {\n\ttestConn.RemoveSessionByIMSI(\"001011234567891\")\n\n\tif testConn.SessionCount() != len(sessions)-1 {\n\t\tt.Errorf(\"Session not removed expectedly: %d, %v\", testConn.SessionCount(), testConn.Sessions())\n\t}\n\n\tfor i := 2; i <= testConn.SessionCount(); i++ {\n\t\tsess, err := testConn.GetSessionByTEID(uint32(i), dummyAddr)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tlastDigit := strconv.Itoa(i)\n\t\tif string(sess.IMSI[14]) != lastDigit {\n\t\t\tt.Errorf(\"Got wrong session at %d, %s\", i, sess.IMSI)\n\t\t}\n\t}\n\n\t// add the session again\n\ts := gtpv2.NewSession(dummyAddr, &gtpv2.Subscriber{IMSI: \"001011234567891\"})\n\t_ = s.Activate()\n\ts.AddTEID(gtpv2.IFTypeS11MMEGTPC, uint32(0))\n\ttestConn.RegisterSession(0, s)\n}\n"
  },
  {
    "path": "gtpv2/ie/ambr.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewAggregateMaximumBitRate creates a new AggregateMaximumBitRate IE.\nfunc NewAggregateMaximumBitRate(up, down uint32) *IE {\n\tv := NewAggregateMaximumBitRateFields(up, down)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(AggregateMaximumBitRate, 0x00, b)\n}\n\n// AggregateMaximumBitRate returns AggregateMaximumBitRate in AggregateMaximumBitRateFields type if the type of IE matches.\nfunc (i *IE) AggregateMaximumBitRate() (*AggregateMaximumBitRateFields, error) {\n\tswitch i.Type {\n\tcase AggregateMaximumBitRate:\n\t\treturn ParseAggregateMaximumBitRateFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// AggregateMaximumBitRateFields is a set of fields in AggregateMaximumBitRate IE.\ntype AggregateMaximumBitRateFields struct {\n\tAPNAMBRForUplink   uint32\n\tAPNAMBRForDownlink uint32\n}\n\n// NewAggregateMaximumBitRateFields creates a new AggregateMaximumBitRateFields.\nfunc NewAggregateMaximumBitRateFields(up, down uint32) *AggregateMaximumBitRateFields {\n\treturn &AggregateMaximumBitRateFields{\n\t\tAPNAMBRForUplink:   up,\n\t\tAPNAMBRForDownlink: down,\n\t}\n}\n\n// Marshal serializes AggregateMaximumBitRateFields.\nfunc (f *AggregateMaximumBitRateFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes AggregateMaximumBitRateFields.\nfunc (f *AggregateMaximumBitRateFields) MarshalTo(b []byte) error {\n\tif len(b) < 8 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tbinary.BigEndian.PutUint32(b[0:4], f.APNAMBRForUplink)\n\tbinary.BigEndian.PutUint32(b[4:8], f.APNAMBRForDownlink)\n\n\treturn nil\n}\n\n// ParseAggregateMaximumBitRateFields decodes AggregateMaximumBitRateFields.\nfunc ParseAggregateMaximumBitRateFields(b []byte) (*AggregateMaximumBitRateFields, error) {\n\tf := &AggregateMaximumBitRateFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into AggregateMaximumBitRateFields.\nfunc (f *AggregateMaximumBitRateFields) UnmarshalBinary(b []byte) error {\n\tif len(b) < 8 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.APNAMBRForUplink = binary.BigEndian.Uint32(b[0:4])\n\tf.APNAMBRForDownlink = binary.BigEndian.Uint32(b[4:8])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of AggregateMaximumBitRateFields in int.\nfunc (f *AggregateMaximumBitRateFields) MarshalLen() int {\n\treturn 8\n}\n\n// AggregateMaximumBitRateUp returns AggregateMaximumBitRate for Uplink\n// if the type of IE matches.\nfunc (i *IE) AggregateMaximumBitRateUp() (uint32, error) {\n\tif i.Type != AggregateMaximumBitRate {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload[0:4]), nil\n}\n\n// MustAggregateMaximumBitRateUp returns AggregateMaximumBitRateUp in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAggregateMaximumBitRateUp() uint32 {\n\tv, _ := i.AggregateMaximumBitRateUp()\n\treturn v\n}\n\n// AggregateMaximumBitRateDown returns AggregateMaximumBitRate for Downlink\n// if the type of IE matches.\nfunc (i *IE) AggregateMaximumBitRateDown() (uint32, error) {\n\tif i.Type != AggregateMaximumBitRate {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 8 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload[4:8]), nil\n}\n\n// MustAggregateMaximumBitRateDown returns AggregateMaximumBitRateDown in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAggregateMaximumBitRateDown() uint32 {\n\tv, _ := i.AggregateMaximumBitRateDown()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/apn-restriction.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewAPNRestriction creates a new APNRestriction IE.\nfunc NewAPNRestriction(restriction uint8) *IE {\n\treturn NewUint8IE(APNRestriction, restriction)\n}\n\n// APNRestriction returns APNRestriction in uint8 if the type of IE matches.\nfunc (i *IE) APNRestriction() (uint8, error) {\n\tif i.Type != APNRestriction {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\n\treturn i.ValueAsUint8()\n}\n\n// MustAPNRestriction returns APNRestriction in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAPNRestriction() uint8 {\n\tv, _ := i.APNRestriction()\n\treturn v\n}\n\n// RestrictionType returns RestrictionType in uint8 if the type of IE matches.\nfunc (i *IE) RestrictionType() (uint8, error) {\n\treturn i.APNRestriction()\n}\n"
  },
  {
    "path": "gtpv2/ie/apn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewAccessPointName creates a new AccessPointName IE.\nfunc NewAccessPointName(apn string) *IE {\n\treturn NewFQDNIE(AccessPointName, apn)\n}\n\n// AccessPointName returns AccessPointName in string if the type of IE matches.\nfunc (i *IE) AccessPointName() (string, error) {\n\tif i.Type != AccessPointName {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsFQDN()\n}\n\n// MustAccessPointName returns AccessPointName in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAccessPointName() string {\n\tv, _ := i.AccessPointName()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/arp.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewAllocationRetensionPriority creates a new AllocationRetensionPriority IE.\nfunc NewAllocationRetensionPriority(pci, pl, pvi uint8) *IE {\n\ti := New(AllocationRetensionPriority, 0x00, make([]byte, 1))\n\ti.Payload[0] |= (pci << 6 & 0x40) | (pl << 2 & 0x3c) | (pvi & 0x01)\n\treturn i\n}\n\n// AllocationRetensionPriority returns AllocationRetensionPriority in uint8 if the type of IE matches.\nfunc (i *IE) AllocationRetensionPriority() (uint8, error) {\n\tif i.Type != AllocationRetensionPriority {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// HasPVI reports whether an IE has PVI bit.\nfunc (i *IE) HasPVI() bool {\n\tv, err := i.AllocationRetensionPriority()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v)\n}\n\n// HasPCI reports whether an IE has PCI bit.\nfunc (i *IE) HasPCI() bool {\n\tv, err := i.AllocationRetensionPriority()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v)\n}\n\n// PriorityLevel returns PriorityLevel in uint8 if the type of IE matches.\nfunc (i *IE) PriorityLevel() (uint8, error) {\n\tswitch i.Type {\n\tcase AllocationRetensionPriority:\n\t\tv, err := i.AllocationRetensionPriority()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\treturn (v & 0x3c) >> 2, nil\n\tcase BearerQoS:\n\t\tv, err := i.BearerQoS()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\treturn (v.ARP & 0x3c) >> 2, nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// PreemptionVulnerability reports whether the preemption vulnerability is set to enabled if the type of IE matches.\n//\n// Deprecated: use HasPVI instead.\nfunc (i *IE) PreemptionVulnerability() bool {\n\treturn i.HasPVI()\n}\n\n// PreemptionCapability reports whether the preemption capability is set to enabled if the type of IE matches.\n//\n// Deprecated: use HasPCI instead.\nfunc (i *IE) PreemptionCapability() bool {\n\treturn i.HasPCI()\n}\n"
  },
  {
    "path": "gtpv2/ie/bearer-context.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewBearerContext creates a new BearerContext IE.\nfunc NewBearerContext(ies ...*IE) *IE {\n\treturn NewGroupedIE(BearerContext, ies...)\n}\n\n// NewBearerContextWithinCreateBearerRequest creates a new BearerContext used within CreateBearerRequest.\nfunc NewBearerContextWithinCreateBearerRequest(ebi, tft, qos, chargeID, flags, pco, epco, mplr *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi, tft, qos, chargeID, flags, pco, epco, mplr}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinCreateBearerResponse creates a new BearerContext used within CreateBearerResponse.\nfunc NewBearerContextWithinCreateBearerResponse(ebi, cause, pco, rannasCause, epco *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi, cause, pco, rannasCause, epco}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinDeleteBearerRequest creates a new BearerContext used within DeleteBearerRequest.\nfunc NewBearerContextWithinDeleteBearerRequest(ebi, cause *IE) *IE {\n\treturn NewBearerContext(ebi, cause)\n}\n\n// NewBearerContextWithinDeleteBearerResponse creates a new BearerContext used within DeleteBearerResponse.\nfunc NewBearerContextWithinDeleteBearerResponse(ebi, cause, pco, rannasCause, epco *IE) *IE {\n\treturn NewBearerContext(ebi, cause, pco, rannasCause, epco)\n}\n\n// NewBearerContextWithinModifyBearerCommand creates a new BearerContext used within ModifyBearerCommand.\nfunc NewBearerContextWithinModifyBearerCommand(ebi, qos *IE) *IE {\n\treturn NewBearerContext(ebi, qos)\n}\n\n// NewBearerContextWithinUpdateBearerRequest creates a new BearerContext used within UpdateBearerRequest.\nfunc NewBearerContextWithinUpdateBearerRequest(ebi, tft, qos, flags, pco, apco, epco, mplr *IE) *IE {\n\treturn NewBearerContext(ebi, tft, qos, flags, pco, apco, epco, mplr)\n}\n\n// NewBearerContextWithinUpdateBearerResponse creates a new BearerContext used within UpdateBearerResponse.\nfunc NewBearerContextWithinUpdateBearerResponse(ebi, cause, pco, rannasCause, epco *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi, cause, pco, rannasCause, epco}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinDeleteBearerCommand creates a new BearerContext used within DeleteBearerCommand.\nfunc NewBearerContextWithinDeleteBearerCommand(ebi, flags, rannasCause *IE) *IE {\n\treturn NewBearerContext(ebi, flags, rannasCause)\n}\n\n// NewBearerContextWithinDeleteBearerFailureIndication creates a new BearerContext used within DeleteBearerFailureIndication.\nfunc NewBearerContextWithinDeleteBearerFailureIndication(ebi, cause *IE) *IE {\n\treturn NewBearerContext(ebi, cause)\n}\n\n// NewBearerContextWithinCreateIndirectDataForwardingTunnelRequest creates a new BearerContext used within CreateIndirectDataForwardingTunnelRequest.\nfunc NewBearerContextWithinCreateIndirectDataForwardingTunnelRequest(ebi *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinCreateIndirectDataForwardingTunnelResponse creates a new BearerContext used within CreateIndirectDataForwardingTunnelResponse.\nfunc NewBearerContextWithinCreateIndirectDataForwardingTunnelResponse(ebi, cause *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi, cause}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinForwardRelocationRequest creates a new BearerContext used within  ForwardRelocationRequest.\nfunc NewBearerContextWithinForwardRelocationRequest(ebi, tft, qos, container, ti, flags *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi, tft, qos, container, ti, flags}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinContextResponse creates a new BearerContext used within  ContextResponse.\nfunc NewBearerContextWithinContextResponse(ebi, tft, qos, container, ti *IE, fTEIDs ...*IE) *IE {\n\ties := []*IE{ebi, tft, qos, container, ti}\n\ties = append(ies, fTEIDs...)\n\treturn NewBearerContext(ies...)\n}\n\n// NewBearerContextWithinContextAcknowledge creates a new BearerContext used within ContextAcknowledge.\nfunc NewBearerContextWithinContextAcknowledge(ebi, fwdFTEID *IE) *IE {\n\treturn NewBearerContext(ebi, fwdFTEID)\n}\n\n// BearerContext returns the []*IE inside BearerContext IE.\nfunc (i *IE) BearerContext() ([]*IE, error) {\n\tif i.Type != BearerContext {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\ties, err := ParseMultiIEs(i.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ies, nil\n}\n"
  },
  {
    "path": "gtpv2/ie/bearer-flags.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewBearerFlags creates a new BearerFlags IE.\nfunc NewBearerFlags(asi, vInd, vb, ppc uint8) *IE {\n\ti := New(BearerFlags, 0x00, make([]byte, 1))\n\ti.Payload[0] |= ((asi << 3 & 0x08) | (vInd << 2 & 0x04) | (vb << 1 & 0x2) | ppc&0x01)\n\treturn i\n}\n\n// BearerFlags returns BearerFlags in uint8(=as it is) if the type of IE matches.\nfunc (i *IE) BearerFlags() (uint8, error) {\n\tswitch i.Type {\n\tcase BearerFlags:\n\t\treturn i.ValueAsUint8()\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == BearerFlags {\n\t\t\t\treturn child.BearerFlags()\n\t\t\t}\n\t\t}\n\t\treturn 0, ErrIENotFound\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustBearerFlags returns BearerFlags in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustBearerFlags() uint8 {\n\tv, _ := i.BearerFlags()\n\treturn v\n}\n\n// HasPPC reports whether an IE has PPC bit.\nfunc (i *IE) HasPPC() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v)\n}\n\n// HasVB reports whether an IE has VB bit.\nfunc (i *IE) HasVB() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v)\n}\n\n// HasVind reports whether an IE has Vind bit.\nfunc (i *IE) HasVind() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v)\n}\n\n// HasASI reports whether an IE has ASI bit.\nfunc (i *IE) HasASI() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v)\n}\n\n// ActivityStatusIndicator reports whether the bearer context is preserved in\n// the CN without corresponding Radio Access Bearer established.\nfunc (i *IE) ActivityStatusIndicator() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn v&0x08 == 1\n}\n\n// VSRVCC reports whether this bearer is an IMS video bearer and is candidate\n// for PS-to-CS vSRVCC handover.\nfunc (i *IE) VSRVCC() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn v&0x04 == 1\n}\n\n// VoiceBearer reports whether a voice bearer when doing PS-to-CS (v)SRVCC handover.\nfunc (i *IE) VoiceBearer() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn v&0x02 == 1\n}\n\n// ProhibitPayloadCompression reports whether an SGSN should attempt to\n// compress the payload of user data when the users asks for it to be compressed.\nfunc (i *IE) ProhibitPayloadCompression() bool {\n\tv, err := i.BearerFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn v&0x01 == 1\n}\n"
  },
  {
    "path": "gtpv2/ie/bearer-qos.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewBearerQoS creates a new BearerQoS IE.\nfunc NewBearerQoS(pci, pl, pvi, qci uint8, umbr, dmbr, ugbr, dgbr uint64) *IE {\n\tv := NewBearerQoSFields(pci, pl, pvi, qci, umbr, dmbr, ugbr, dgbr)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(BearerQoS, 0x00, b)\n}\n\n// BearerQoS returns BearerQoS in BearerQoSFields type if the type of IE matches.\nfunc (i *IE) BearerQoS() (*BearerQoSFields, error) {\n\tswitch i.Type {\n\tcase BearerQoS:\n\t\treturn ParseBearerQoSFields(i.Payload)\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to retrieve BearerQoS: %w\", err)\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == BearerQoS {\n\t\t\t\treturn child.BearerQoS()\n\t\t\t}\n\t\t}\n\t\treturn nil, ErrIENotFound\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// BearerQoSFields is a set of fields in BearerQoS IE.\ntype BearerQoSFields struct {\n\tARP                          uint8\n\tQCI                          uint8\n\tMaximumBitRateForUplink      uint64 // 40 bits\n\tMaximumBitRateForDownlink    uint64 // 40 bits\n\tGuaranteedBitRateForUplink   uint64 // 40 bits\n\tGuaranteedBitRateForDownlink uint64 // 40 bits\n}\n\n// NewBearerQoSFields creates a new BearerQoSFields.\nfunc NewBearerQoSFields(pci, pl, pvi, qci uint8, umbr, dmbr, ugbr, dgbr uint64) *BearerQoSFields {\n\treturn &BearerQoSFields{\n\t\tARP:                          (pci << 6 & 0x40) | (pl << 2 & 0x3c) | (pvi & 0x01),\n\t\tQCI:                          qci,\n\t\tMaximumBitRateForUplink:      umbr,\n\t\tMaximumBitRateForDownlink:    dmbr,\n\t\tGuaranteedBitRateForUplink:   ugbr,\n\t\tGuaranteedBitRateForDownlink: dgbr,\n\t}\n}\n\n// Marshal serializes BearerQoSFields.\nfunc (f *BearerQoSFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes BearerQoSFields.\nfunc (f *BearerQoSFields) MarshalTo(b []byte) error {\n\tif len(b) < 22 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.ARP\n\tb[1] = f.QCI\n\n\tcopy(b[2:7], utils.Uint64To40(f.MaximumBitRateForUplink))\n\tcopy(b[7:12], utils.Uint64To40(f.MaximumBitRateForDownlink))\n\tcopy(b[12:17], utils.Uint64To40(f.GuaranteedBitRateForUplink))\n\tcopy(b[17:22], utils.Uint64To40(f.GuaranteedBitRateForDownlink))\n\n\treturn nil\n}\n\n// ParseBearerQoSFields decodes BearerQoSFields.\nfunc ParseBearerQoSFields(b []byte) (*BearerQoSFields, error) {\n\tf := &BearerQoSFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into BearerQoSFields.\nfunc (f *BearerQoSFields) UnmarshalBinary(b []byte) error {\n\tif len(b) < 22 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.ARP = b[0]\n\tf.QCI = b[1]\n\n\tf.MaximumBitRateForUplink = utils.Uint40To64(b[2:7])\n\tf.MaximumBitRateForDownlink = utils.Uint40To64(b[7:12])\n\tf.GuaranteedBitRateForUplink = utils.Uint40To64(b[12:17])\n\tf.GuaranteedBitRateForDownlink = utils.Uint40To64(b[17:22])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of BearerQoSFields in int.\nfunc (f *BearerQoSFields) MarshalLen() int {\n\treturn 22\n}\n\n// QCILabel returns QCILabel in uint8 if the type of IE matches.\nfunc (i *IE) QCILabel() (uint8, error) {\n\tswitch i.Type {\n\tcase BearerQoS:\n\t\tif len(i.Payload) < 2 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[1], nil\n\tcase FlowQoS:\n\t\treturn i.ValueAsUint8()\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MBRForUplink returns MBRForUplink in uint64 if the type of IE matches.\nfunc (i *IE) MBRForUplink() (uint64, error) {\n\tswitch i.Type {\n\tcase BearerQoS:\n\t\tif len(i.Payload) < 7 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[2:7]), nil\n\tcase FlowQoS:\n\t\tif len(i.Payload) < 6 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[2:6]), nil\n\tdefault:\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n}\n\n// MustMBRForUplink returns MBRForUplink in uint64, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMBRForUplink() uint64 {\n\tv, _ := i.MBRForUplink()\n\treturn v\n}\n\n// MBRForDownlink returns MBRForDownlink in uint64 if the type of IE matches.\nfunc (i *IE) MBRForDownlink() (uint64, error) {\n\tswitch i.Type {\n\tcase BearerQoS:\n\t\tif len(i.Payload) < 12 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[7:12]), nil\n\tcase FlowQoS:\n\t\tif len(i.Payload) < 11 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[6:11]), nil\n\tdefault:\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n}\n\n// MustMBRForDownlink returns MBRForDownlink in uint64, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMBRForDownlink() uint64 {\n\tv, _ := i.MBRForDownlink()\n\treturn v\n}\n\n// GBRForUplink returns GBRForUplink in uint64 if the type of IE matches.\nfunc (i *IE) GBRForUplink() (uint64, error) {\n\tswitch i.Type {\n\tcase BearerQoS:\n\t\tif len(i.Payload) < 17 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[12:17]), nil\n\tcase FlowQoS:\n\t\tif len(i.Payload) < 16 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[11:16]), nil\n\tdefault:\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n}\n\n// MustGBRForUplink returns GBRForUplink in uint64, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustGBRForUplink() uint64 {\n\tv, _ := i.GBRForUplink()\n\treturn v\n}\n\n// GBRForDownlink returns GBRForDownlink in uint64 if the type of IE matches.\nfunc (i *IE) GBRForDownlink() (uint64, error) {\n\tswitch i.Type {\n\tcase BearerQoS:\n\t\tif len(i.Payload) < 22 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[17:22]), nil\n\tcase FlowQoS:\n\t\tif len(i.Payload) < 21 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint40To64(i.Payload[16:21]), nil\n\tdefault:\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n}\n\n// MustGBRForDownlink returns GBRForDownlink in uint64, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustGBRForDownlink() uint64 {\n\tv, _ := i.GBRForDownlink()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/bearer-tft.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// TFT Operation Code definitions.\nconst (\n\tTFTOpIgnoreThisIE                       uint8 = 0\n\tTFTOpCreateNewTFT                       uint8 = 1\n\tTFTOpDeleteExistingTFT                  uint8 = 2\n\tTFTOpAddPacketFiltersToExistingTFT      uint8 = 3\n\tTFTOpReplacePacketFiltersInExistingTFT  uint8 = 4\n\tTFTOpDeletePacketFiltersFromExistingTFT uint8 = 5\n\tTFTOpNoTFTOperation                     uint8 = 6\n)\n\n// NewBearerTFT creates a new BearerTFT IE.\n//\n// Custom constructors for each operation code are available, which does not require\n// unnecessary parameters.\nfunc NewBearerTFT(op uint8, filters []*TFTPacketFilter, ids []uint8, params []*TFTParameter) *IE {\n\tv := NewTrafficFlowTemplate(op, filters, ids, params)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(BearerTFT, 0x00, b)\n}\n\n// NewBearerTFTCreateNewTFT creates a new BearerTFT IE with opcode=CreateNewTFT.\nfunc NewBearerTFTCreateNewTFT(filters []*TFTPacketFilter, params []*TFTParameter) *IE {\n\treturn NewBearerTFT(TFTOpCreateNewTFT, filters, nil, params)\n}\n\n// NewBearerTFTAddPacketFilters creates a new BearerTFT IE with opcode=AddPacketFiltersToExistingTFT.\nfunc NewBearerTFTAddPacketFilters(filters []*TFTPacketFilter, params []*TFTParameter) *IE {\n\treturn NewBearerTFT(TFTOpAddPacketFiltersToExistingTFT, filters, nil, params)\n}\n\n// NewBearerTFTReplacePacketFilters creates a new BearerTFT IE with opcode=ReplacePacketFiltersInExistingTFT.\nfunc NewBearerTFTReplacePacketFilters(filters []*TFTPacketFilter, params []*TFTParameter) *IE {\n\treturn NewBearerTFT(TFTOpReplacePacketFiltersInExistingTFT, filters, nil, params)\n}\n\n// NewBearerTFTDeletePacketFilters creates a new BearerTFT IE with opcode=DeletePacketFiltersFromExistingTFT.\nfunc NewBearerTFTDeletePacketFilters(ids []uint8, params ...*TFTParameter) *IE {\n\treturn NewBearerTFT(TFTOpDeletePacketFiltersFromExistingTFT, nil, ids, params)\n}\n\n// NewBearerTFTDeleteExistingTFT creates a new BearerTFT IE with opcode=DeleteExistingTFT.\nfunc NewBearerTFTDeleteExistingTFT(params ...*TFTParameter) *IE {\n\treturn NewBearerTFT(TFTOpDeleteExistingTFT, nil, nil, params)\n}\n\n// NewBearerTFTNoTFTOperation creates a new BearerTFT IE with opcode=NoTFTOperation.\nfunc NewBearerTFTNoTFTOperation(params ...*TFTParameter) *IE {\n\treturn NewBearerTFT(TFTOpNoTFTOperation, nil, nil, params)\n}\n\n// BearerTFT returns TrafficFlowTemplate struct if the type of IE matches.\nfunc (i *IE) BearerTFT() (*TrafficFlowTemplate, error) {\n\treturn i.TrafficFlowTemplate()\n}\n"
  },
  {
    "path": "gtpv2/ie/cause.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// NewCause creates a new Cause IE.\nfunc NewCause(cause uint8, pce, bce, cs uint8, offendingIE *IE) *IE {\n\ti := New(Cause, 0x00, make([]byte, 2))\n\ti.Payload[0] = cause\n\ti.Payload[1] = ((pce << 2) & 0x04) | ((bce << 1) & 0x02) | cs&0x01\n\n\tif offendingIE != nil {\n\t\t// trailing zeroes are length, instance and spare fields which should be\n\t\t// filled with zeroes in this case (cf. §8.4, TS29.274)\n\t\ti.Payload = append(i.Payload, []byte{offendingIE.Type, 0x00, 0x00, 0x00}...)\n\t\ti.SetLength()\n\t}\n\treturn i\n}\n\n// Cause returns Cause in uint8 if the type of IE matches.\nfunc (i *IE) Cause() (uint8, error) {\n\tswitch i.Type {\n\tcase Cause:\n\t\treturn i.ValueAsUint8()\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn 0, fmt.Errorf(\"failed to retrieve Cause: %w\", err)\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == Cause {\n\t\t\t\treturn child.Cause()\n\t\t\t}\n\t\t}\n\t\treturn 0, ErrIENotFound\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCause returns Cause in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCause() uint8 {\n\tv, _ := i.Cause()\n\treturn v\n}\n\n// CauseFlags returns CauseFlags in uint8 if the type of IE matches.\nfunc (i *IE) CauseFlags() (uint8, error) {\n\tswitch i.Type {\n\tcase Cause:\n\t\tif len(i.Payload) < 2 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\n\t\treturn i.Payload[1], nil\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn 0, fmt.Errorf(\"failed to retrieve Cause: %w\", err)\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == Cause {\n\t\t\t\treturn child.Cause()\n\t\t\t}\n\t\t}\n\t\treturn 0, ErrIENotFound\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCauseFlags returns CauseFlags in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCauseFlags() uint8 {\n\tv, _ := i.CauseFlags()\n\treturn v\n}\n\n// HasCS reports whether an IE has CS bit.\nfunc (i *IE) HasCS() bool {\n\tv, err := i.CauseFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v)\n}\n\n// HasBCE reports whether an IE has BCE bit.\nfunc (i *IE) HasBCE() bool {\n\tv, err := i.CauseFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v)\n}\n\n// HasPCE reports whether an IE has PCE bit.\nfunc (i *IE) HasPCE() bool {\n\tv, err := i.CauseFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v)\n}\n\n// IsRemoteCause returns IsRemoteCause in bool if the type of IE matches.\nfunc (i *IE) IsRemoteCause() bool {\n\tif i.Type != Cause {\n\t\treturn false\n\t}\n\n\tif len(i.Payload) < 2 {\n\t\treturn false\n\t}\n\n\tif i.Payload[1]>>2&0x01 == 1 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// IsBearerContextIEError returns IsBearerContextIEError in bool if the type of IE matches.\nfunc (i *IE) IsBearerContextIEError() bool {\n\tif i.Type != Cause {\n\t\treturn false\n\t}\n\n\tif len(i.Payload) < 2 {\n\t\treturn false\n\t}\n\n\tif i.Payload[1]>>1&0x01 == 1 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// IsPDNConnectionIEError returns IsPDNConnectionIEError in bool if the type of IE matches.\nfunc (i *IE) IsPDNConnectionIEError() bool {\n\tif i.Type != Cause {\n\t\treturn false\n\t}\n\n\tif len(i.Payload) < 2 {\n\t\treturn false\n\t}\n\n\tif i.Payload[1]&0x01 == 1 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// OffendingIE returns OffendingIE in *IE if the type of IE matches.\n//\n// Note that the returned IE has no payload (cf. §8.4, TS29.274).\nfunc (i *IE) OffendingIE() (*IE, error) {\n\tif i.Type != Cause {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\n\tif len(i.Payload) < 6 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn Parse(i.Payload[2:6])\n}\n\n// MustOffendingIE returns OffendingIE in *IE, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustOffendingIE() *IE {\n\tv, _ := i.OffendingIE()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/charging-characteristics.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewChargingCharacteristics creates a new ChargingCharacteristics IE.\nfunc NewChargingCharacteristics(chr uint16) *IE {\n\treturn NewUint16IE(ChargingCharacteristics, chr)\n}\n\n// ChargingCharacteristics returns the ChargingCharacteristics value in uint16 if the type of IE matches.\nfunc (i *IE) ChargingCharacteristics() (uint16, error) {\n\tif i.Type != ChargingCharacteristics {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint16()\n}\n\n// MustChargingCharacteristics returns ChargingCharacteristics in uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustChargingCharacteristics() uint16 {\n\tv, _ := i.ChargingCharacteristics()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/charging-id.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewChargingID creates a new ChargingID IE.\nfunc NewChargingID(id uint32) *IE {\n\treturn NewUint32IE(ChargingID, id)\n}\n\n// ChargingID returns the ChargingID value in uint32 if the type of IE matches.\nfunc (i *IE) ChargingID() (uint32, error) {\n\tswitch i.Type {\n\tcase ChargingID:\n\t\treturn i.ValueAsUint32()\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == ChargingID {\n\t\t\t\treturn child.ChargingID()\n\t\t\t}\n\t\t}\n\t\treturn 0, ErrIENotFound\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustChargingID returns ChargingID in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustChargingID() uint32 {\n\tv, _ := i.ChargingID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/cmi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"io\"\n\n// NewCSGMembershipIndication creates a new CSGMembershipIndication IE.\nfunc NewCSGMembershipIndication(cmi uint8) *IE {\n\treturn NewUint8IE(CSGMembershipIndication, cmi)\n}\n\n// CMI returns CMI in uint8 if the type of IE matches.\nfunc (i *IE) CMI() (uint8, error) {\n\tswitch i.Type {\n\tcase CSGMembershipIndication:\n\t\treturn i.ValueAsUint8()\n\tcase UserCSGInformation:\n\t\tif len(i.Payload) < 8 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[7], nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCMI returns CMI in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCMI() uint8 {\n\tv, _ := i.CMI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/csg-id.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewCSGID creates a new CSGID IE.\nfunc NewCSGID(id uint32) *IE {\n\treturn NewUint32IE(CSGID, id&0x7ffffff)\n}\n\n// CSGID returns CSGID in uint32 if the type of IE matches.\nfunc (i *IE) CSGID() (uint32, error) {\n\tswitch i.Type {\n\tcase CSGID:\n\t\treturn i.ValueAsUint32()\n\tcase UserCSGInformation:\n\t\tif len(i.Payload) < 7 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint32(i.Payload[3:7]) & 0x7ffffff, nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCSGID returns CSGID in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCSGID() uint32 {\n\tv, _ := i.CSGID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/delay-value.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"time\"\n)\n\n// NewDelayValue creates a new DelayValue IE.\nfunc NewDelayValue(delay time.Duration) *IE {\n\treturn NewUint8IE(DelayValue, uint8(delay.Seconds()*1000/50))\n}\n\n// NewDelayValueRaw creates a new DelayValue IE from a uint8 value.\n//\n// The value should be in multiples of 50ms or zero.\nfunc NewDelayValueRaw(delay uint8) *IE {\n\treturn NewUint8IE(DelayValue, delay)\n}\n\n// DelayValue returns DelayValue in time.Duration if the type of IE matches.\n//\n// The returned value is in time.Duration. To get the value in multiples of 50ms,\n// use ValueAsUint8 or access Payload field directly instead.\nfunc (i *IE) DelayValue() (time.Duration, error) {\n\tif i.Type != DelayValue {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn time.Duration(i.Payload[0]/50) * time.Millisecond, nil\n}\n\n// MustDelayValue returns DelayValue in time.Duration, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustDelayValue() time.Duration {\n\tv, _ := i.DelayValue()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/detach-type.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewDetachType creates a new DetachType IE.\nfunc NewDetachType(dtype uint8) *IE {\n\treturn NewUint8IE(DetachType, dtype)\n}\n\n// DetachType returns DetachType in uint8 if the type of IE matches.\nfunc (i *IE) DetachType() (uint8, error) {\n\tif i.Type != DetachType {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustDetachType returns DetachType in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustDetachType() uint8 {\n\tv, _ := i.DetachType()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/ebi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewEPSBearerID creates a new EPSBearerID IE.\nfunc NewEPSBearerID(ebi uint8) *IE {\n\treturn NewUint8IE(EPSBearerID, ebi&0x0f)\n}\n\n// EPSBearerID returns EPSBearerID if the type of IE matches.\nfunc (i *IE) EPSBearerID() (uint8, error) {\n\tswitch i.Type {\n\tcase EPSBearerID:\n\t\treturn i.ValueAsUint8()\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == EPSBearerID {\n\t\t\t\treturn child.EPSBearerID()\n\t\t\t}\n\t\t}\n\t\treturn 0, ErrIENotFound\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustEPSBearerID returns EPSBearerID in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustEPSBearerID() uint8 {\n\tv, _ := i.EPSBearerID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/epc-timer.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"math\"\n\t\"time\"\n)\n\n// NewEPCTimer creates a new EPCTimer IE.\nfunc NewEPCTimer(duration time.Duration) *IE {\n\t// 8.87 EPC Timer\n\t// Timer unit\n\t// Bits 6 to 8 defines the timer value unit as follows: Bits\n\t// 8 7 6\n\t// 0 0 0 value is incremented in multiples of 2 seconds\n\t// 0 0 1 value is incremented in multiples of 1 minute\n\t// 0 1 0 value is incremented in multiples of 10 minutes\n\t// 0 1 1 value is incremented in multiples of 1 hour\n\t// 1 0 0 value is incremented in multiples of 10 hours\n\t// 1 1 1 value indicates that the timer is infinite\n\t//\n\t// Other values shall be interpreted as multiples of 1 minute in this version of the protocol.\n\t// Timer unit and Timer value both set to all \"zeros\" shall be interpreted as an indication that the timer is stopped.\n\n\tvar unit, value uint8\n\tswitch {\n\tcase duration%(10*time.Hour) == 0:\n\t\tunit = 0x80\n\t\tvalue = uint8(duration / (10 * time.Hour))\n\tcase duration%(1*time.Hour) == 0:\n\t\tunit = 0x60\n\t\tvalue = uint8(duration / time.Hour)\n\tcase duration%(10*time.Minute) == 0:\n\t\tunit = 0x40\n\t\tvalue = uint8(duration / (10 * time.Minute))\n\tcase duration%(1*time.Minute) == 0:\n\t\tunit = 0x20\n\t\tvalue = uint8(duration / time.Minute)\n\tcase duration%(2*time.Second) == 0:\n\t\tunit = 0x00\n\t\tvalue = uint8(duration / (2 * time.Second))\n\tdefault:\n\t\tunit = 0xe0\n\t\tvalue = 0\n\t}\n\n\treturn NewUint8IE(EPCTimer, unit+(value&0x1f))\n}\n\n// NewEPCTimerRaw creates a new EPCTimer IE from a uint8 value.\nfunc NewEPCTimerRaw(duration uint8) *IE {\n\treturn NewUint8IE(EPCTimer, duration)\n}\n\n// EPCTimer returns EPCTimer in time.Duration if the type of IE matches.\n//\n// The returned value is in time.Duration. To get the raw value as uint8,\n// use ValueAsUint8 or access Payload field directly instead.\nfunc (i *IE) EPCTimer() (time.Duration, error) {\n\treturn i.Timer()\n}\n\n// MustEPCTimer returns EPCTimer in time.Duration, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustEPCTimer() time.Duration {\n\tv, _ := i.EPCTimer()\n\treturn v\n}\n\n// Timer returns Timer in time.Duration if the type of IE matches.\nfunc (i *IE) Timer() (time.Duration, error) {\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase EPCTimer:\n\t\tvar d time.Duration\n\t\tswitch (i.Payload[0] & 0xe0) >> 5 {\n\t\tcase 0x07:\n\t\t\td = time.Duration(math.MaxInt64)\n\t\tcase 0x04:\n\t\t\td = time.Duration(i.Payload[0]&0x1f) * 10 * time.Hour\n\t\tcase 0x03:\n\t\t\td = time.Duration(i.Payload[0]&0x1f) * time.Hour\n\t\tcase 0x02:\n\t\t\td = time.Duration(i.Payload[0]&0x1f) * 10 * time.Minute\n\t\tcase 0x01:\n\t\t\td = time.Duration(i.Payload[0]&0x1f) * time.Minute\n\t\tcase 0x00:\n\t\t\td = time.Duration(i.Payload[0]&0x1f) * 2 * time.Second\n\t\tdefault:\n\t\t\td = 0\n\t\t}\n\t\treturn d, nil\n\tcase OverloadControlInformation:\n\t\treturn 0, errors.New(\"not implemented\")\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n"
  },
  {
    "path": "gtpv2/ie/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Error definitions.\nvar (\n\tErrTooShortToParse = errors.New(\"too short to decode as GTP\")\n\tErrInvalidLength   = errors.New(\"length value is invalid\")\n\n\tErrInvalidType     = errors.New(\"invalid type\")\n\tErrIENotFound      = errors.New(\"could not find the specified IE in a grouped IE\")\n\tErrIEValueNotFound = errors.New(\"could not find the specified value in an IE\")\n\n\tErrMalformed = errors.New(\"malformed IE\")\n)\n\n// InvalidTypeError indicates the type of IE is invalid.\ntype InvalidTypeError struct {\n\tType uint8\n}\n\n// Error returns message with the invalid type given.\nfunc (e *InvalidTypeError) Error() string {\n\treturn fmt.Sprintf(\"got invalid type: %v\", e.Type)\n}\n"
  },
  {
    "path": "gtpv2/ie/f-teid.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"net\"\n)\n\n// NewFullyQualifiedTEID creates a new FullyQualifiedTEID IE.\nfunc NewFullyQualifiedTEID(ifType uint8, teid uint32, v4, v6 string) *IE {\n\tv := NewFullyQualifiedTEIDFields(ifType, teid, net.ParseIP(v4), net.ParseIP(v6))\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(FullyQualifiedTEID, 0x00, b)\n}\n\n// NewFullyQualifiedTEIDNetIP creates a new FullyQualifiedTEID IE from net.IP instead of string.\nfunc NewFullyQualifiedTEIDNetIP(ifType uint8, teid uint32, v4, v6 net.IP) *IE {\n\tv := NewFullyQualifiedTEIDFields(ifType, teid, v4, v6)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(FullyQualifiedTEID, 0x00, b)\n}\n\n// FullyQualifiedTEID returns FullyQualifiedTEID in FullyQualifiedTEIDFields type if the type of IE matches.\nfunc (i *IE) FullyQualifiedTEID() (*FullyQualifiedTEIDFields, error) {\n\tswitch i.Type {\n\tcase FullyQualifiedTEID:\n\t\treturn ParseFullyQualifiedTEIDFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// FullyQualifiedTEIDFields is a set of fields in FullyQualifiedTEID IE.\ntype FullyQualifiedTEIDFields struct {\n\tFlags         uint8 // 7-8th bit, in the same octet as InterfaceType\n\tInterfaceType uint8 // 1-6-bit, in the same octet as Flags\n\tTEIDGREKey    uint32\n\tIPv4Address   net.IP\n\tIPv6Address   net.IP\n}\n\n// NewFullyQualifiedTEIDFields creates a new FullyQualifiedTEIDFields.\nfunc NewFullyQualifiedTEIDFields(ifType uint8, teid uint32, v4, v6 net.IP) *FullyQualifiedTEIDFields {\n\tf := &FullyQualifiedTEIDFields{\n\t\tInterfaceType: ifType,\n\t\tTEIDGREKey:    teid,\n\t}\n\n\tif v := v4.To4(); v != nil {\n\t\tf.Flags |= 0x80\n\t\tf.IPv4Address = v\n\t}\n\tif v := v6.To16(); v != nil {\n\t\tf.Flags |= 0x40\n\t\tf.IPv6Address = v\n\t}\n\n\treturn f\n}\n\n// Marshal serializes FullyQualifiedTEIDFields.\nfunc (f *FullyQualifiedTEIDFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes FullyQualifiedTEIDFields.\nfunc (f *FullyQualifiedTEIDFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 5 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.InterfaceType\n\tbinary.BigEndian.PutUint32(b[1:5], f.TEIDGREKey)\n\toffset := 5\n\n\tif f.IPv4Address != nil {\n\t\tif l < offset+4 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tif v := f.IPv4Address.To4(); v != nil {\n\t\t\tb[0] |= 0x80\n\t\t\tcopy(b[offset:offset+4], v)\n\t\t\toffset += 4\n\t\t}\n\t}\n\tif f.IPv6Address != nil {\n\t\tif l < offset+16 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tif v := f.IPv6Address.To16(); v != nil {\n\t\t\tb[0] |= 0x40\n\t\t\tcopy(b[offset:offset+16], v)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// ParseFullyQualifiedTEIDFields decodes FullyQualifiedTEIDFields.\nfunc ParseFullyQualifiedTEIDFields(b []byte) (*FullyQualifiedTEIDFields, error) {\n\tf := &FullyQualifiedTEIDFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into FullyQualifiedTEIDFields.\nfunc (f *FullyQualifiedTEIDFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 5 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.Flags = b[0] & 0xc0\n\tf.InterfaceType = b[0] & 0x3f\n\tf.TEIDGREKey = binary.BigEndian.Uint32(b[1:5])\n\toffset := 5\n\n\tif has8thBit(f.Flags) { // has IPv4Address\n\t\tif l < offset+4 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tif v := net.IP(b[offset : offset+4]).To4(); v != nil {\n\t\t\tf.IPv4Address = v\n\t\t\toffset += 4\n\t\t}\n\t}\n\tif has7thBit(f.Flags) { // has IPv6Address\n\t\tif l < offset+16 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tif v := net.IP(b[offset : offset+16]).To16(); v != nil {\n\t\t\tf.IPv6Address = v\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of FullyQualifiedTEIDFields in int.\nfunc (f *FullyQualifiedTEIDFields) MarshalLen() int {\n\tl := 5\n\tif has8thBit(f.Flags) { // has IPv4Address\n\t\tl += 4\n\t}\n\tif has7thBit(f.Flags) { // has IPv6Address\n\t\tl += 16\n\t}\n\n\treturn l\n}\n\n// HasIPv4 reports whether an IE has IPv4 bit.\nfunc (i *IE) HasIPv4() bool {\n\tswitch i.Type {\n\tcase FullyQualifiedTEID:\n\t\tif len(i.Payload) < 1 {\n\t\t\treturn false\n\t\t}\n\n\t\treturn has8thBit(i.Payload[0])\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// HasIPv6 reports whether an IE has IPv6 bit.\nfunc (i *IE) HasIPv6() bool {\n\tswitch i.Type {\n\tcase FullyQualifiedTEID:\n\t\tif len(i.Payload) < 1 {\n\t\t\treturn false\n\t\t}\n\n\t\treturn has7thBit(i.Payload[0])\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// InterfaceType returns InterfaceType in uint8 if the type of IE matches.\nfunc (i *IE) InterfaceType() (uint8, error) {\n\tif i.Type != FullyQualifiedTEID {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0] & 0x3f, nil\n}\n\n// MustInterfaceType returns InterfaceType in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustInterfaceType() uint8 {\n\tv, _ := i.InterfaceType()\n\treturn v\n}\n\n// GREKey returns GREKey in uint32 if the type of IE matches.\nfunc (i *IE) GREKey() (uint32, error) {\n\tif len(i.Payload) < 6 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\tswitch i.Type {\n\tcase FullyQualifiedTEID:\n\t\treturn binary.BigEndian.Uint32(i.Payload[1:5]), nil\n\tcase S103PDNDataForwardingInfo:\n\t\tswitch i.Payload[0] {\n\t\tcase 4:\n\t\t\tif len(i.Payload) < 9 {\n\t\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn binary.BigEndian.Uint32(i.Payload[5:9]), nil\n\t\tcase 16:\n\t\t\tif len(i.Payload) < 21 {\n\t\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn binary.BigEndian.Uint32(i.Payload[17:21]), nil\n\t\tdefault:\n\t\t\treturn 0, ErrMalformed\n\t\t}\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustGREKey returns GREKey in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustGREKey() uint32 {\n\tv, _ := i.GREKey()\n\treturn v\n}\n\n// TEID returns TEID in uint32 if the type of IE matches.\nfunc (i *IE) TEID() (uint32, error) {\n\tif len(i.Payload) < 5 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\tswitch i.Type {\n\tcase FullyQualifiedTEID:\n\t\treturn binary.BigEndian.Uint32(i.Payload[1:5]), nil\n\tcase S1UDataForwarding:\n\t\tswitch i.Payload[0] {\n\t\tcase 4:\n\t\t\tif len(i.Payload) < 9 {\n\t\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn binary.BigEndian.Uint32(i.Payload[5:9]), nil\n\t\tcase 16:\n\t\t\tif len(i.Payload) < 21 {\n\t\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn binary.BigEndian.Uint32(i.Payload[17:21]), nil\n\t\tdefault:\n\t\t\treturn 0, ErrMalformed\n\t\t}\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\n}\n\n// MustTEID returns TEID in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTEID() uint32 {\n\tv, _ := i.TEID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/flow-qos.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewFlowQoS creates a new FlowQoS IE.\nfunc NewFlowQoS(qci uint8, umbr, dmbr, ugbr, dgbr uint64) *IE {\n\tv := NewFlowQoSFields(qci, umbr, dmbr, ugbr, dgbr)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(FlowQoS, 0x00, b)\n}\n\n// FlowQoS returns FlowQoS in FlowQoSFields type if the type of IE matches.\nfunc (i *IE) FlowQoS() (*FlowQoSFields, error) {\n\tswitch i.Type {\n\tcase FlowQoS:\n\t\treturn ParseFlowQoSFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// FlowQoSFields is a set of fields in FlowQoS IE.\ntype FlowQoSFields struct {\n\tQCI                          uint8\n\tMaximumBitRateForUplink      uint64 // 40 bits\n\tMaximumBitRateForDownlink    uint64 // 40 bits\n\tGuaranteedBitRateForUplink   uint64 // 40 bits\n\tGuaranteedBitRateForDownlink uint64 // 40 bits\n}\n\n// NewFlowQoSFields creates a new FlowQoSFields.\nfunc NewFlowQoSFields(qci uint8, umbr, dmbr, ugbr, dgbr uint64) *FlowQoSFields {\n\treturn &FlowQoSFields{\n\t\tQCI:                          qci,\n\t\tMaximumBitRateForUplink:      umbr,\n\t\tMaximumBitRateForDownlink:    dmbr,\n\t\tGuaranteedBitRateForUplink:   ugbr,\n\t\tGuaranteedBitRateForDownlink: dgbr,\n\t}\n}\n\n// Marshal serializes FlowQoSFields.\nfunc (f *FlowQoSFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes FlowQoSFields.\nfunc (f *FlowQoSFields) MarshalTo(b []byte) error {\n\tif len(b) < 21 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.QCI\n\n\tcopy(b[1:6], utils.Uint64To40(f.MaximumBitRateForUplink))\n\tcopy(b[6:11], utils.Uint64To40(f.MaximumBitRateForDownlink))\n\tcopy(b[11:16], utils.Uint64To40(f.GuaranteedBitRateForUplink))\n\tcopy(b[16:21], utils.Uint64To40(f.GuaranteedBitRateForDownlink))\n\n\treturn nil\n}\n\n// ParseFlowQoSFields decodes FlowQoSFields.\nfunc ParseFlowQoSFields(b []byte) (*FlowQoSFields, error) {\n\tf := &FlowQoSFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into FlowQoSFields.\nfunc (f *FlowQoSFields) UnmarshalBinary(b []byte) error {\n\tif len(b) < 21 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.QCI = b[0]\n\n\tf.MaximumBitRateForUplink = utils.Uint40To64(b[1:6])\n\tf.MaximumBitRateForDownlink = utils.Uint40To64(b[6:11])\n\tf.GuaranteedBitRateForUplink = utils.Uint40To64(b[11:16])\n\tf.GuaranteedBitRateForDownlink = utils.Uint40To64(b[16:21])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of FlowQoSFields in int.\nfunc (f *FlowQoSFields) MarshalLen() int {\n\treturn 21\n}\n"
  },
  {
    "path": "gtpv2/ie/fq-csid.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"encoding/hex\"\n\t\"io\"\n\t\"net\"\n)\n\n// Node-ID Type definitions.\nconst (\n\tnodeIDIPv4 uint8 = iota\n\tnodeIDIPv6\n\tnodeIDOther\n)\n\n// NewFullyQualifiedCSID creates a new FullyQualifiedCSID IE.\nfunc NewFullyQualifiedCSID(nodeID string, csIDs ...uint16) *IE {\n\tv := NewFullyQualifiedCSIDFields(nodeID, csIDs...)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(FullyQualifiedCSID, 0x00, b)\n}\n\n// FullyQualifiedCSID returns FullyQualifiedCSID in FullyQualifiedCSIDFields type if the type of IE matches.\nfunc (i *IE) FullyQualifiedCSID() (*FullyQualifiedCSIDFields, error) {\n\tswitch i.Type {\n\tcase FullyQualifiedCSID:\n\t\treturn ParseFullyQualifiedCSIDFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// FullyQualifiedCSIDFields is a set of fields in FullyQualifiedCSID IE.\ntype FullyQualifiedCSIDFields struct {\n\tNodeIDType    uint8 // 4-bit\n\tNumberOfCSIDs uint8 // 4-bit\n\tNodeID        []byte\n\tCSIDs         []uint16\n}\n\n// NewFullyQualifiedCSIDFields creates a new FullyQualifiedCSIDFields.\nfunc NewFullyQualifiedCSIDFields(nodeID string, csIDs ...uint16) *FullyQualifiedCSIDFields {\n\tf := &FullyQualifiedCSIDFields{\n\t\tNumberOfCSIDs: uint8(len(csIDs)),\n\t\tCSIDs:         csIDs,\n\t}\n\n\tip := net.ParseIP(nodeID)\n\tif ip == nil {\n\t\tvar err error\n\t\tf.NodeID, err = hex.DecodeString(nodeID)\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tf.NodeIDType = nodeIDOther\n\t} else if v4 := ip.To4(); v4 != nil {\n\t\tf.NodeID = v4\n\t\tf.NodeIDType = nodeIDIPv4\n\t} else {\n\t\tf.NodeID = ip\n\t\tf.NodeIDType = nodeIDIPv6\n\t}\n\n\treturn f\n}\n\n// Marshal serializes FullyQualifiedCSIDFields.\nfunc (f *FullyQualifiedCSIDFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes FullyQualifiedCSIDFields.\nfunc (f *FullyQualifiedCSIDFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = ((f.NodeIDType << 4) & 0xf0) | (f.NumberOfCSIDs & 0x0f)\n\toffset := 1\n\n\tif l < offset+len(f.NodeID) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+len(f.NodeID)], f.NodeID)\n\toffset += len(f.NodeID)\n\n\tfor n, csid := range f.CSIDs {\n\t\tif l < offset+n*2+2 {\n\t\t\tbreak\n\t\t}\n\t\tbinary.BigEndian.PutUint16(b[offset+n*2:offset+n*2+2], csid)\n\t}\n\n\treturn nil\n}\n\n// ParseFullyQualifiedCSIDFields decodes FullyQualifiedCSIDFields.\nfunc ParseFullyQualifiedCSIDFields(b []byte) (*FullyQualifiedCSIDFields, error) {\n\tf := &FullyQualifiedCSIDFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into FullyQualifiedCSIDFields.\nfunc (f *FullyQualifiedCSIDFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.NodeIDType = (b[0] >> 4) & 0x0f\n\tf.NumberOfCSIDs = b[0] & 0x0f\n\toffset := 1\n\n\tswitch f.NodeIDType {\n\tcase nodeIDIPv4, nodeIDOther:\n\t\tif l < offset+4 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tf.NodeID = b[offset : offset+4]\n\t\toffset += 4\n\tcase nodeIDIPv6:\n\t\tif l < offset+16 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tf.NodeID = b[offset : offset+16]\n\t\toffset += 16\n\tdefault:\n\t\treturn ErrMalformed\n\t}\n\n\tfor {\n\t\tif l < offset+2 {\n\t\t\tbreak\n\t\t}\n\t\tf.CSIDs = append(f.CSIDs, binary.BigEndian.Uint16(b[offset:offset+2]))\n\t\toffset += 2\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of FullyQualifiedCSIDFields in int.\nfunc (f *FullyQualifiedCSIDFields) MarshalLen() int {\n\tl := 1\n\n\tswitch f.NodeIDType {\n\tcase nodeIDIPv4, nodeIDOther:\n\t\tl += 4\n\tcase nodeIDIPv6:\n\t\tl += 16\n\tdefault:\n\n\t}\n\n\tl += len(f.CSIDs) * 2\n\treturn l\n}\n\n// NodeIDType returns NodeIDType in uint8 if the type of IE matches.\nfunc (i *IE) NodeIDType() (uint8, error) {\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase FullyQualifiedCSID:\n\t\treturn (i.Payload[0] >> 4) & 0x0f, nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustNodeIDType returns NodeIDType in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustNodeIDType() uint8 {\n\tv, _ := i.NodeIDType()\n\treturn v\n}\n\n// NodeID returns NodeID in []byte if the type of IE matches.\nfunc (i *IE) NodeID() ([]byte, error) {\n\tif len(i.Payload) < 1 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase FullyQualifiedCSID:\n\t\tswitch (i.Payload[0] >> 4) & 0x0f {\n\t\tcase nodeIDIPv4, nodeIDOther:\n\t\t\tif len(i.Payload) < 6 {\n\t\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn i.Payload[1:5], nil\n\t\tcase nodeIDIPv6:\n\t\t\tif len(i.Payload) < 18 {\n\t\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn i.Payload[1:17], nil\n\t\tdefault:\n\t\t\treturn nil, ErrMalformed\n\t\t}\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustNodeID returns NodeID in []byte, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustNodeID() []byte {\n\tv, _ := i.NodeID()\n\treturn v\n}\n\n// CSIDs returns CSIDs in []uint16 if the type of IE matches.\nfunc (i *IE) CSIDs() ([]uint16, error) {\n\tif len(i.Payload) < 1 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase FullyQualifiedCSID:\n\t\toffset := 0\n\t\tswitch (i.Payload[0] >> 4) & 0x0f {\n\t\tcase nodeIDIPv4, nodeIDOther:\n\t\t\toffset += 5\n\t\tcase nodeIDIPv6:\n\t\t\toffset += 17\n\t\tdefault:\n\t\t\treturn nil, ErrMalformed\n\t\t}\n\n\t\tvar csids []uint16\n\t\tfor {\n\t\t\tif offset+2 > len(i.Payload) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcsids = append(csids, binary.BigEndian.Uint16(i.Payload[offset:offset+2]))\n\t\t\toffset += 2\n\t\t}\n\t\treturn csids, nil\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCSIDs returns CSIDs in []uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCSIDs() []uint16 {\n\tv, _ := i.CSIDs()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/fqdn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewFullyQualifiedDomainName creates a new FullyQualifiedDomainName IE.\nfunc NewFullyQualifiedDomainName(fqdn string) *IE {\n\treturn NewFQDNIE(FullyQualifiedDomainName, fqdn)\n}\n\n// FullyQualifiedDomainName returns FullyQualifiedDomainName in string if the type of IE matches.\nfunc (i *IE) FullyQualifiedDomainName() (string, error) {\n\tif i.Type != FullyQualifiedDomainName {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsFQDN()\n}\n\n// MustFullyQualifiedDomainName returns FullyQualifiedDomainName in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustFullyQualifiedDomainName() string {\n\tv, _ := i.FullyQualifiedDomainName()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/global-cn-id.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewGlobalCNID creates a new GlobalCNID IE.\nfunc NewGlobalCNID(mcc, mnc string, cnid uint16) *IE {\n\ti := New(GlobalCNID, 0x00, make([]byte, 5))\n\tplmn, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tcopy(i.Payload[0:3], plmn)\n\n\tcnid &= 0xfff\n\tbinary.BigEndian.PutUint16(i.Payload[3:5], cnid)\n\treturn i\n}\n\n// CNID returns CNID in uinte16 if the type of IE matches.\nfunc (i *IE) CNID() (uint16, error) {\n\tif len(i.Payload) < 5 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\tswitch i.Type {\n\tcase GlobalCNID:\n\t\treturn binary.BigEndian.Uint16(i.Payload[3:5]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustCNID returns CNID in uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustCNID() uint16 {\n\tv, _ := i.CNID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/guti.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewGUTI creates a new GUTI IE.\nfunc NewGUTI(mcc, mnc string, groupID uint16, code uint8, mTMSI uint32) *IE {\n\tv := NewGUTIFields(mcc, mnc, groupID, code, mTMSI)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(GUTI, 0x00, b)\n}\n\n// GUTI returns GUTI in GUTIFields type if the type of IE matches.\nfunc (i *IE) GUTI() (*GUTIFields, error) {\n\tswitch i.Type {\n\tcase GUTI:\n\t\treturn ParseGUTIFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// GUTIFields is a set of fields in GUTI IE.\ntype GUTIFields struct {\n\tMCC, MNC   string\n\tMMEGroupID uint16\n\tMMECode    uint8\n\tMTMSI      uint32\n}\n\n// NewGUTIFields creates a new GUTIFields.\nfunc NewGUTIFields(mcc, mnc string, groupID uint16, code uint8, mTMSI uint32) *GUTIFields {\n\treturn &GUTIFields{\n\t\tMCC:        mcc,\n\t\tMNC:        mnc,\n\t\tMMEGroupID: groupID,\n\t\tMMECode:    code,\n\t\tMTMSI:      mTMSI,\n\t}\n}\n\n// Marshal serializes GUTIFields.\nfunc (f *GUTIFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes GUTIFields.\nfunc (f *GUTIFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tplmn, err := utils.EncodePLMN(f.MCC, f.MNC)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tcopy(b[0:3], plmn)\n\n\tif l < 10 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tbinary.BigEndian.PutUint16(b[3:5], f.MMEGroupID)\n\tb[5] = f.MMECode\n\tbinary.BigEndian.PutUint32(b[6:10], f.MTMSI)\n\n\treturn nil\n}\n\n// ParseGUTIFields decodes GUTIFields.\nfunc ParseGUTIFields(b []byte) (*GUTIFields, error) {\n\tf := &GUTIFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into GUTIFields.\nfunc (f *GUTIFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tvar err error\n\tf.MCC, f.MNC, err = utils.DecodePLMN(b[1:3])\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif l < 10 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.MMEGroupID = binary.BigEndian.Uint16(b[3:5])\n\tf.MMECode = b[5]\n\tf.MTMSI = binary.BigEndian.Uint32(b[6:10])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of GUTIFields in int.\nfunc (f *GUTIFields) MarshalLen() int {\n\treturn 10\n}\n\n// MMEGroupID returns MMEGroupID in uint16 if the type of IE matches.\nfunc (i *IE) MMEGroupID() (uint16, error) {\n\tswitch i.Type {\n\tcase GUTI:\n\t\tif len(i.Payload) < 5 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint16(i.Payload[3:5]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMMEGroupID returns MMEGroupID in uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMMEGroupID() uint16 {\n\tv, _ := i.MMEGroupID()\n\treturn v\n}\n\n// MMECode returns MMECode in uint8 if the type of IE matches.\nfunc (i *IE) MMECode() (uint8, error) {\n\tswitch i.Type {\n\tcase GUTI:\n\t\tif len(i.Payload) < 6 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[5], nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMMECode returns MMECode in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMMECode() uint8 {\n\tv, _ := i.MMECode()\n\treturn v\n}\n\n// MTMSI returns MTMSI in uint32 if the type of IE matches.\nfunc (i *IE) MTMSI() (uint32, error) {\n\tswitch i.Type {\n\tcase GUTI:\n\t\tif len(i.Payload) < 10 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn binary.BigEndian.Uint32(i.Payload[6:10]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMTMSI returns MTMSI in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMTMSI() uint32 {\n\tv, _ := i.MTMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/hop-counter.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewHopCounter creates a new HopCounter IE.\nfunc NewHopCounter(hop uint8) *IE {\n\treturn NewUint8IE(HopCounter, hop)\n}\n\n// HopCounter returns HopCounter in uint8 if the type of IE matches.\nfunc (i *IE) HopCounter() (uint8, error) {\n\tif i.Type != HopCounter {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustHopCounter returns HopCounter in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustHopCounter() uint8 {\n\tv, _ := i.HopCounter()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/ie.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n/*\nPackage ie provides encoding/decoding feature of GTPv2 Information Elements.\n*/\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// IE definitions.\nconst (\n\tIMSI                                                 uint8 = 1\n\tCause                                                uint8 = 2\n\tRecovery                                             uint8 = 3\n\tSTNSR                                                uint8 = 51\n\tAccessPointName                                      uint8 = 71\n\tAggregateMaximumBitRate                              uint8 = 72\n\tEPSBearerID                                          uint8 = 73\n\tIPAddress                                            uint8 = 74\n\tMobileEquipmentIdentity                              uint8 = 75\n\tMSISDN                                               uint8 = 76\n\tIndication                                           uint8 = 77\n\tProtocolConfigurationOptions                         uint8 = 78\n\tPDNAddressAllocation                                 uint8 = 79\n\tBearerQoS                                            uint8 = 80\n\tFlowQoS                                              uint8 = 81\n\tRATType                                              uint8 = 82\n\tServingNetwork                                       uint8 = 83\n\tBearerTFT                                            uint8 = 84\n\tTrafficAggregateDescription                          uint8 = 85\n\tUserLocationInformation                              uint8 = 86\n\tFullyQualifiedTEID                                   uint8 = 87\n\tTMSI                                                 uint8 = 88\n\tGlobalCNID                                           uint8 = 89\n\tS103PDNDataForwardingInfo                            uint8 = 90\n\tS1UDataForwarding                                    uint8 = 91\n\tDelayValue                                           uint8 = 92\n\tBearerContext                                        uint8 = 93\n\tChargingID                                           uint8 = 94\n\tChargingCharacteristics                              uint8 = 95\n\tTraceInformation                                     uint8 = 96\n\tBearerFlags                                          uint8 = 97\n\tPDNType                                              uint8 = 99\n\tProcedureTransactionID                               uint8 = 100\n\tMMContextGSMKeyAndTriplets                           uint8 = 103\n\tMMContextUMTSKeyUsedCipherAndQuintuplets             uint8 = 104\n\tMMContextGSMKeyUsedCipherAndQuintuplets              uint8 = 105\n\tMMContextUMTSKeyAndQuintuplets                       uint8 = 106\n\tMMContextEPSSecurityContextQuadrupletsAndQuintuplets uint8 = 107\n\tMMContextUMTSKeyQuadrupletsAndQuintuplets            uint8 = 108\n\tPDNConnection                                        uint8 = 109\n\tPDUNumbers                                           uint8 = 110\n\tPacketTMSI                                           uint8 = 111\n\tPTMSISignature                                       uint8 = 112\n\tHopCounter                                           uint8 = 113\n\tUETimeZone                                           uint8 = 114\n\tTraceReference                                       uint8 = 115\n\tCompleteRequestMessage                               uint8 = 116\n\tGUTI                                                 uint8 = 117\n\tFContainer                                           uint8 = 118\n\tFCause                                               uint8 = 119\n\tPLMNID                                               uint8 = 120\n\tTargetIdentification                                 uint8 = 121\n\tPacketFlowID                                         uint8 = 123\n\tRABContext                                           uint8 = 124\n\tSourceRNCPDCPContextInfo                             uint8 = 125\n\tPortNumber                                           uint8 = 126\n\tAPNRestriction                                       uint8 = 127\n\tSelectionMode                                        uint8 = 128\n\tSourceIdentification                                 uint8 = 129\n\tChangeReportingAction                                uint8 = 131\n\tFullyQualifiedCSID                                   uint8 = 132\n\tChannelNeeded                                        uint8 = 133\n\tEMLPPPriority                                        uint8 = 134\n\tNodeType                                             uint8 = 135\n\tFullyQualifiedDomainName                             uint8 = 136\n\tTI                                                   uint8 = 137\n\tMBMSSessionDuration                                  uint8 = 138\n\tMBMSServiceArea                                      uint8 = 139\n\tMBMSSessionIdentifier                                uint8 = 140\n\tMBMSFlowIdentifier                                   uint8 = 141\n\tMBMSIPMulticastDistribution                          uint8 = 142\n\tMBMSDistributionAcknowledge                          uint8 = 143\n\tRFSPIndex                                            uint8 = 144\n\tUserCSGInformation                                   uint8 = 145\n\tCSGInformationReportingAction                        uint8 = 146\n\tCSGID                                                uint8 = 147\n\tCSGMembershipIndication                              uint8 = 148\n\tServiceIndicator                                     uint8 = 149\n\tDetachType                                           uint8 = 150\n\tLocalDistinguishedName                               uint8 = 151\n\tNodeFeatures                                         uint8 = 152\n\tMBMSTimeToDataTransfer                               uint8 = 153\n\tThrottling                                           uint8 = 154\n\tAllocationRetensionPriority                          uint8 = 155\n\tEPCTimer                                             uint8 = 156\n\tSignallingPriorityIndication                         uint8 = 157\n\tTMGI                                                 uint8 = 158\n\tAdditionalMMContextForSRVCC                          uint8 = 159\n\tAdditionalFlagsForSRVCC                              uint8 = 160\n\tMDTConfiguration                                     uint8 = 162\n\tAdditionalProtocolConfigurationOptions               uint8 = 163\n\tAbsoluteTimeofMBMSDataTransfer                       uint8 = 164\n\tHeNBInformationReporting                             uint8 = 165\n\tIPv4ConfigurationParameters                          uint8 = 166\n\tChangeToReportFlags                                  uint8 = 167\n\tActionIndication                                     uint8 = 168\n\tTWANIdentifier                                       uint8 = 169\n\tULITimestamp                                         uint8 = 170\n\tMBMSFlags                                            uint8 = 171\n\tRANNASCause                                          uint8 = 172\n\tCNOperatorSelectionEntity                            uint8 = 173\n\tTrustedWLANModeIndication                            uint8 = 174\n\tNodeNumber                                           uint8 = 175\n\tNodeIdentifier                                       uint8 = 176\n\tPresenceReportingAreaAction                          uint8 = 177\n\tPresenceReportingAreaInformation                     uint8 = 178\n\tTWANIdentifierTimestamp                              uint8 = 179\n\tOverloadControlInformation                           uint8 = 180\n\tLoadControlInformation                               uint8 = 181\n\tMetric                                               uint8 = 182\n\tSequenceNumber                                       uint8 = 183\n\tAPNAndRelativeCapacity                               uint8 = 184\n\tWLANOffloadabilityIndication                         uint8 = 185\n\tPagingAndServiceInformation                          uint8 = 186\n\tIntegerNumber                                        uint8 = 187\n\tMillisecondTimeStamp                                 uint8 = 188\n\tMonitoringEventInformation                           uint8 = 189\n\tECGIList                                             uint8 = 190\n\tRemoteUEContext                                      uint8 = 191\n\tRemoteUserID                                         uint8 = 192\n\tRemoteUEIPinformation                                uint8 = 193\n\tCIoTOptimizationsSupportIndication                   uint8 = 194\n\tSCEFPDNConnection                                    uint8 = 195\n\tHeaderCompressionConfiguration                       uint8 = 196\n\tExtendedProtocolConfigurationOptions                 uint8 = 197\n\tServingPLMNRateControl                               uint8 = 198\n\tCounter                                              uint8 = 199\n\tMappedUEUsageType                                    uint8 = 200\n\tSecondaryRATUsageDataReport                          uint8 = 201\n\tUPFunctionSelectionIndicationFlags                   uint8 = 202\n\tMaximumPacketLossRate                                uint8 = 203\n\tAPNRateControlStatus                                 uint8 = 204\n\tExtendedTraceInformation                             uint8 = 205\n\tMonitoringEventExtensionInformation                  uint8 = 206\n\tAdditionalRRMPolicyIndex                             uint8 = 207\n\tV2XContext                                           uint8 = 208\n\tPC5QoSParameters                                     uint8 = 209\n\tServicesAuthorized                                   uint8 = 210\n\tBitRate                                              uint8 = 211\n\tPC5QoSFlow                                           uint8 = 212\n\tSGiPtPTunnelAddress                                  uint8 = 213\n\tSpecialIETypeForIETypeExtension                      uint8 = 254\n\tPrivateExtension                                     uint8 = 255\n)\n\n// IE is a GTPv2 Information Element.\ntype IE struct {\n\tType     uint8\n\tLength   uint16\n\tinstance uint8\n\tPayload  []byte\n\tChildIEs []*IE\n}\n\n// New creates new IE.\nfunc New(itype, ins uint8, data []byte) *IE {\n\tie := &IE{\n\t\tType:     itype,\n\t\tinstance: ins & 0x0f,\n\t\tPayload:  data,\n\t}\n\tie.SetLength()\n\n\treturn ie\n}\n\n// SetInstance sets the instance.\nfunc (i *IE) SetInstance(ins uint8) {\n\ti.instance = ins & 0x0f\n}\n\n// WithInstance sets the instance and returns IE.\nfunc (i *IE) WithInstance(ins uint8) *IE {\n\ti.instance = ins & 0x0f\n\treturn i\n}\n\n// Instance returns instance value in uint8\nfunc (i *IE) Instance() uint8 {\n\treturn i.instance & 0x0f\n}\n\n// Marshal returns the byte sequence generated from an IE instance.\nfunc (i *IE) Marshal() ([]byte, error) {\n\tb := make([]byte, i.MarshalLen())\n\tif err := i.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (i *IE) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 4 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = i.Type\n\tbinary.BigEndian.PutUint16(b[1:3], i.Length)\n\tb[3] = i.instance\n\tif i.IsGrouped() {\n\t\toffset := 4\n\t\tfor _, ie := range i.ChildIEs {\n\t\t\tif l < offset+ie.MarshalLen() {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tif err := ie.MarshalTo(b[offset : offset+ie.MarshalLen()]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\toffset += ie.MarshalLen()\n\t\t}\n\t\treturn nil\n\t}\n\n\tif l < i.MarshalLen() {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tcopy(b[4:i.MarshalLen()], i.Payload)\n\treturn nil\n}\n\n// Parse decodes given byte sequence as a GTPv2 Information Element.\nfunc Parse(b []byte) (*IE, error) {\n\tie := &IE{}\n\tif err := ie.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ie, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in GTPv2 IE.\nfunc (i *IE) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 4 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\ti.Type = b[0]\n\ti.Length = binary.BigEndian.Uint16(b[1:3])\n\tif int(i.Length) > l-4 {\n\t\treturn ErrInvalidLength\n\t}\n\n\ti.instance = b[3]\n\ti.Payload = b[4 : 4+int(i.Length)]\n\n\tif i.IsGrouped() {\n\t\tvar err error\n\t\ti.ChildIEs, err = ParseMultiIEs(i.Payload)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns field length in integer.\nfunc (i *IE) MarshalLen() int {\n\tif i.IsGrouped() {\n\t\tl := 4\n\t\tfor _, ie := range i.ChildIEs {\n\t\t\tl += ie.MarshalLen()\n\t\t}\n\t\treturn l\n\t}\n\treturn 4 + len(i.Payload)\n}\n\n// SetLength sets the length in Length field.\nfunc (i *IE) SetLength() {\n\tif i.IsGrouped() {\n\t\tl := 0\n\t\tfor _, ie := range i.ChildIEs {\n\t\t\tl += ie.MarshalLen()\n\t\t}\n\t\ti.Length = uint16(l)\n\t}\n\ti.Length = uint16(len(i.Payload))\n}\n\n// Name returns the name of IE in string.\nfunc (i *IE) Name() string {\n\tif n, ok := ieTypeNameMap[i.Type]; ok {\n\t\treturn n\n\t}\n\treturn \"Undefined\"\n}\n\n// String returns the GTPv2 IE values in human readable format.\nfunc (i *IE) String() string {\n\tif i == nil {\n\t\treturn \"nil\"\n\t}\n\treturn fmt.Sprintf(\"{%s: {Type: %d, Length: %d, Instance: %#x, Payload: %#v}}\",\n\t\ti.Name(),\n\t\ti.Type,\n\t\ti.Length,\n\t\ti.Instance(),\n\t\ti.Payload,\n\t)\n}\n\n// ParseMultiIEs decodes multiple IEs at a time.\n// This is easy and useful but slower than decoding one by one.\n// When you don't know the number of IEs, this is the only way to decode them.\n// See benchmarks in diameter_test.go for the detail.\nfunc ParseMultiIEs(b []byte) ([]*IE, error) {\n\tvar ies []*IE\n\tfor {\n\t\tif len(b) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\ti, err := Parse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ties = append(ies, i)\n\t\tb = b[i.MarshalLen():]\n\t}\n\treturn ies, nil\n}\n\n// NewUint8IE creates a new IE with uint8 value.\nfunc NewUint8IE(t, v uint8) *IE {\n\treturn New(t, 0x00, []byte{v})\n}\n\n// NewUint16IE creates a new IE with uint16 value.\nfunc NewUint16IE(t uint8, v uint16) *IE {\n\ti := New(t, 0x00, make([]byte, 2))\n\tbinary.BigEndian.PutUint16(i.Payload, v)\n\treturn i\n}\n\n// NewUint32IE creates a new IE with uint32 value.\nfunc NewUint32IE(t uint8, v uint32) *IE {\n\ti := New(t, 0x00, make([]byte, 4))\n\tbinary.BigEndian.PutUint32(i.Payload, v)\n\treturn i\n}\n\n// NewUint64IE creates a new IE with uint64 value.\nfunc NewUint64IE(t uint8, v uint64) *IE {\n\ti := New(t, 0x00, make([]byte, 8))\n\tbinary.BigEndian.PutUint64(i.Payload, v)\n\treturn i\n}\n\n// NewStringIE creates a new IE with string value.\nfunc NewStringIE(t uint8, v string) *IE {\n\treturn New(t, 0x00, []byte(v))\n}\n\n// NewFQDNIE creates a new IE with FQDN value.\nfunc NewFQDNIE(t uint8, v string) *IE {\n\treturn New(t, 0x00, utils.EncodeFQDN(v))\n}\n\n// ValueAsUint8 returns the value of IE as uint8.\nfunc (i *IE) ValueAsUint8() (uint8, error) {\n\tif i.IsGrouped() {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[0], nil\n}\n\n// ValueAsUint16 returns the value of IE as uint16.\nfunc (i *IE) ValueAsUint16() (uint16, error) {\n\tif i.IsGrouped() {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(i.Payload[0:2]), nil\n}\n\n// ValueAsUint32 returns the value of IE as uint32.\nfunc (i *IE) ValueAsUint32() (uint32, error) {\n\tif i.IsGrouped() {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(i.Payload[0:4]), nil\n}\n\n// ValueAsUint64 returns the value of IE as uint64.\nfunc (i *IE) ValueAsUint64() (uint64, error) {\n\tif i.IsGrouped() {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 8 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint64(i.Payload[0:8]), nil\n}\n\n// ValueAsString returns the value of IE as string.\nfunc (i *IE) ValueAsString() (string, error) {\n\tif i.IsGrouped() {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\n\treturn string(i.Payload), nil\n}\n\n// ValueAsFQDN returns the value of IE as string, decoded as FQDN.\nfunc (i *IE) ValueAsFQDN() (string, error) {\n\tif i.IsGrouped() {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\n\treturn utils.DecodeFQDN(i.Payload), nil\n}\n\nvar ieTypeNameMap = map[uint8]string{\n\t1:   \"IMSI\",\n\t2:   \"Cause\",\n\t3:   \"Recovery\",\n\t51:  \"STNSR\",\n\t71:  \"AccessPointName\",\n\t72:  \"AggregateMaximumBitRate\",\n\t73:  \"EPSBearerID\",\n\t74:  \"IPAddress\",\n\t75:  \"MobileEquipmentIdentity\",\n\t76:  \"MSISDN\",\n\t77:  \"Indication\",\n\t78:  \"ProtocolConfigurationOptions\",\n\t79:  \"PDNAddressAllocation\",\n\t80:  \"BearerQoS\",\n\t81:  \"FlowQoS\",\n\t82:  \"RATType\",\n\t83:  \"ServingNetwork\",\n\t84:  \"BearerTFT\",\n\t85:  \"TrafficAggregateDescription\",\n\t86:  \"UserLocationInformation\",\n\t87:  \"FullyQualifiedTEID\",\n\t88:  \"TMSI\",\n\t89:  \"GlobalCNID\",\n\t90:  \"S103PDNDataForwardingInfo\",\n\t91:  \"S1UDataForwarding\",\n\t92:  \"DelayValue\",\n\t93:  \"BearerContext\",\n\t94:  \"ChargingID\",\n\t95:  \"ChargingCharacteristics\",\n\t96:  \"TraceInformation\",\n\t97:  \"BearerFlags\",\n\t99:  \"PDNType\",\n\t100: \"ProcedureTransactionID\",\n\t103: \"MMContextGSMKeyAndTriplets\",\n\t104: \"MMContextUMTSKeyUsedCipherAndQuintuplets\",\n\t105: \"MMContextGSMKeyUsedCipherAndQuintuplets\",\n\t106: \"MMContextUMTSKeyAndQuintuplets\",\n\t107: \"MMContextEPSSecurityContextQuadrupletsAndQuintuplets\",\n\t108: \"MMContextUMTSKeyQuadrupletsAndQuintuplets\",\n\t109: \"PDNConnection\",\n\t110: \"PDUNumbers\",\n\t111: \"PacketTMSI\",\n\t112: \"PTMSISignature\",\n\t113: \"HopCounter\",\n\t114: \"UETimeZone\",\n\t115: \"TraceReference\",\n\t116: \"CompleteRequestMessage\",\n\t117: \"GUTI\",\n\t118: \"FContainer\",\n\t119: \"FCause\",\n\t121: \"PLMNID\",\n\t122: \"TargetIdentification\",\n\t123: \"PacketFlowID\",\n\t124: \"RABContext\",\n\t125: \"SourceRNCPDCPContextInfo\",\n\t126: \"PortNumber\",\n\t127: \"APNRestriction\",\n\t128: \"SelectionMode\",\n\t129: \"SourceIdentification\",\n\t130: \"Reserved\",\n\t131: \"ChangeReportingAction\",\n\t132: \"FullyQualifiedCSID\",\n\t133: \"ChannelNeeded\",\n\t134: \"EMLPPPriority\",\n\t135: \"NodeType\",\n\t136: \"FullyQualifiedDomainName\",\n\t137: \"TI\",\n\t138: \"MBMSSessionDuration\",\n\t139: \"MBMSServiceArea\",\n\t140: \"MBMSSessionIdentifier\",\n\t141: \"MBMSFlowIdentifier\",\n\t142: \"MBMSIPMulticastDistribution\",\n\t143: \"MBMSDistributionAcknowledge\",\n\t144: \"RFSPIndex\",\n\t145: \"UserCSGInformation\",\n\t146: \"CSGInformationReportingAction\",\n\t147: \"CSGID\",\n\t148: \"CSGMembershipIndication\",\n\t149: \"ServiceIndicator\",\n\t150: \"DetachType\",\n\t151: \"LocalDistinguishedName\",\n\t152: \"NodeFeatures\",\n\t153: \"MBMSTimeToDataTransfer\",\n\t154: \"Throttling\",\n\t155: \"AllocationRetensionPriority\",\n\t156: \"EPCTimer\",\n\t157: \"SignallingPriorityIndication\",\n\t158: \"TMGI\",\n\t159: \"AdditionalMMContextForSRVCC\",\n\t160: \"AdditionalFlagsForSRVCC\",\n\t162: \"MDTConfiguration\",\n\t163: \"AdditionalProtocolConfigurationOptions\",\n\t164: \"AbsoluteTimeofMBMSDataTransfer\",\n\t165: \"HeNBInformationReporting\",\n\t166: \"IPv4ConfigurationParameters\",\n\t167: \"ChangeToReportFlags\",\n\t168: \"ActionIndication\",\n\t169: \"TWANIdentifier\",\n\t170: \"ULITimestamp\",\n\t171: \"MBMSFlags\",\n\t172: \"RANNASCause\",\n\t173: \"CNOperatorSelectionEntity\",\n\t174: \"TrustedWLANModeIndication\",\n\t175: \"NodeNumber\",\n\t176: \"NodeIdentifier\",\n\t177: \"PresenceReportingAreaAction\",\n\t178: \"PresenceReportingAreaInformation\",\n\t179: \"TWANIdentifierTimestamp\",\n\t180: \"OverloadControlInformation\",\n\t181: \"LoadControlInformation\",\n\t182: \"Metric\",\n\t183: \"SequenceNumber\",\n\t184: \"APNAndRelativeCapacity\",\n\t185: \"WLANOffloadabilityIndication\",\n\t186: \"PagingAndServiceInformation\",\n\t187: \"IntegerNumber\",\n\t188: \"MillisecondTimeStamp\",\n\t189: \"MonitoringEventInformation\",\n\t190: \"ECGIList\",\n\t191: \"RemoteUEContext\",\n\t192: \"RemoteUserID\",\n\t193: \"RemoteUEIPinformation\",\n\t194: \"CIoTOptimizationsSupportIndication\",\n\t195: \"SCEFPDNConnection\",\n\t196: \"HeaderCompressionConfiguration\",\n\t197: \"ExtendedProtocolConfigurationOptions\",\n\t198: \"ServingPLMNRateControl\",\n\t199: \"Counter\",\n\t200: \"MappedUEUsageType\",\n\t201: \"SecondaryRATUsageDataReport\",\n\t202: \"UPFunctionSelectionIndicationFlags\",\n\t203: \"MaximumPacketLossRate\",\n\t204: \"APNRateControlStatus\",\n\t205: \"ExtendedTraceInformation\",\n\t206: \"MonitoringEventExtensionInformation\",\n\t207: \"AdditionalRRMPolicyIndex\",\n\t208: \"V2XContext\",\n\t209: \"PC5QoSParameters\",\n\t210: \"ServicesAuthorized\",\n\t211: \"BitRate\",\n\t212: \"PC5QoSFlow\",\n\t213: \"SGiPtPTunnelAddress\",\n\t254: \"SpecialIETypeForIETypeExtension\",\n\t255: \"PrivateExtension\",\n}\n"
  },
  {
    "path": "gtpv2/ie/ie_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"log\"\n\n// Serialize serializes IE into bytes.\n//\n// Deprecated: use IE.Marshal instead.\nfunc (i *IE) Serialize() ([]byte, error) {\n\tlog.Println(\"IE.Serialize is deprecated. use IE.Marshal instead\")\n\treturn i.Marshal()\n}\n\n// SerializeTo serializes IE into bytes given as b.\n//\n// Deprecated: use IE.MarshalTo instead.\nfunc (i *IE) SerializeTo(b []byte) error {\n\tlog.Println(\"IE.SerializeTo is deprecated. use IE.MarshalTo instead\")\n\treturn i.MarshalTo(b)\n}\n\n// Decode decodes bytes as IE.\n//\n// Deprecated: use Parse instead.\nfunc Decode(b []byte) (*IE, error) {\n\tlog.Println(\"Decode is deprecated. use Parse instead\")\n\treturn Parse(b)\n}\n\n// DecodeFromBytes decodes bytes as IE.\n//\n// Deprecated: use IE.UnmarshalBinary instead.\nfunc (i *IE) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"IE.DecodeFromBytes is deprecated. use IE.UnmarshalBinary instead\")\n\treturn i.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of IE.\n//\n// Deprecated: use IE.MarshalLen instead.\nfunc (i *IE) Len() int {\n\tlog.Println(\"IE.Len is deprecated. use IE.MarshalLen instead\")\n\treturn i.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/ie/ie_fuzz_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\tfor _, c := range cases {\n\t\tf.Add(c.serialized)\n\t}\n\n\ttestIE := func(t *testing.T, v *ie.IE) {\n\t\t// Generated with\n\t\t// grep -ho -e \"Must.*()\" * | sort | uniq | sed -e 's/^/v./'\n\t\tv.MustAccessMode()\n\t\tv.MustAccessPointName()\n\t\tv.MustAggregateMaximumBitRateDown()\n\t\tv.MustAggregateMaximumBitRateUp()\n\t\tv.MustAPNRestriction()\n\t\tv.MustBearerFlags()\n\t\tv.MustCause()\n\t\tv.MustCauseFlags()\n\t\tv.MustChargingCharacteristics()\n\t\tv.MustChargingID()\n\t\tv.MustCMI()\n\t\tv.MustCNID()\n\t\tv.MustCSGID()\n\t\tv.MustCSIDs()\n\t\tv.MustDaylightSaving()\n\t\tv.MustDelayValue()\n\t\tv.MustDetachType()\n\t\tv.MustEBIs()\n\t\tv.MustEnterpriseID()\n\t\tv.MustEPCTimer()\n\t\tv.MustEPSBearerID()\n\t\tv.MustFullyQualifiedDomainName()\n\t\tv.MustGBRForDownlink()\n\t\tv.MustGBRForUplink()\n\t\tv.MustGREKey()\n\t\tv.MustHopCounter()\n\t\tv.MustHSGWAddress()\n\t\tv.MustIMSI()\n\t\tv.MustIntegerNumber()\n\t\tv.MustInterfaceType()\n\t\tv.MustIP()\n\t\tv.MustIPAddress()\n\t\tv.MustIPv4()\n\t\tv.MustIPv6()\n\t\tv.MustLocalDistinguishedName()\n\t\tv.MustMBMSFlags()\n\t\tv.MustMBRForDownlink()\n\t\tv.MustMBRForUplink()\n\t\tv.MustMCC()\n\t\tv.MustMMECode()\n\t\tv.MustMMEGroupID()\n\t\tv.MustMNC()\n\t\tv.MustMobileEquipmentIdentity()\n\t\tv.MustMSISDN()\n\t\tv.MustMTMSI()\n\t\tv.MustNodeFeatures()\n\t\tv.MustNodeID()\n\t\tv.MustNodeIDType()\n\t\tv.MustNodeType()\n\t\tv.MustOffendingIE()\n\t\tv.MustPacketTMSI()\n\t\tv.MustPagingPolicyIndication()\n\t\tv.MustPDNType()\n\t\tv.MustPLMNID()\n\t\tv.MustPortNumber()\n\t\tv.MustPrivateExtension()\n\t\tv.MustProcedureTransactionID()\n\t\tv.MustProtocolConfigurationOptions()\n\t\tv.MustPTMSISignature()\n\t\tv.MustRATType()\n\t\tv.MustRecovery()\n\t\tv.MustRFSPIndex()\n\t\tv.MustSelectionMode()\n\t\tv.MustServiceIndicator()\n\t\tv.MustServingNetwork()\n\t\tv.MustSGWAddress()\n\t\tv.MustTEID()\n\t\tv.MustTimestamp()\n\t\tv.MustTimeZone()\n\t\tv.MustTMSI()\n\t\tv.MustTraceID()\n\t}\n\n\tf.Fuzz(func(t *testing.T, data []byte) {\n\t\tif v, err := ie.Parse(data); err == nil && v == nil {\n\t\t\tt.Errorf(\"nil without error\")\n\t\t} else if err == nil {\n\t\t\ttestIE(t, v)\n\t\t\tfor _, cie := range v.ChildIEs {\n\t\t\t\ttestIE(t, cie)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv2/ie/ie_grouped.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport \"sync\"\n\n// NewGroupedIE creates a new IE with the given IEs.\n//\n// The IEs with nil value will be ignored.\nfunc NewGroupedIE(itype uint8, ies ...*IE) *IE {\n\ti := New(itype, 0x00, make([]byte, 0))\n\tfor _, ie := range ies {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tserialized, err := ie.Marshal()\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\n\t\ti.Payload = append(i.Payload, serialized...)\n\t\ti.ChildIEs = append(i.ChildIEs, ie)\n\t}\n\ti.SetLength()\n\n\treturn i\n}\n\n// We're using map to avoid iterating over a list.\n// The value `true` is not actually used.\n// TODO: consider using a slice with utils in slices package introduced in Go 1.21.\nvar (\n\tmu                  sync.RWMutex\n\tdefaultGroupedIEMap = map[uint8]bool{\n\t\tBearerContext:              true,\n\t\tPDNConnection:              true,\n\t\tOverloadControlInformation: true,\n\t\tLoadControlInformation:     true,\n\t\tRemoteUEContext:            true,\n\t\tSCEFPDNConnection:          true,\n\t\tV2XContext:                 true,\n\t\tPC5QoSParameters:           true,\n\t}\n\tisGroupedFun = func(t uint8) bool {\n\t\tmu.RLock()\n\t\tdefer mu.RUnlock()\n\t\t_, ok := defaultGroupedIEMap[t]\n\t\treturn ok\n\t}\n)\n\n// SetIsGroupedFun sets a function to check if an IE is of grouped type or not.\nfunc SetIsGroupedFun(fun func(t uint8) bool) {\n\tmu.Lock()\n\tdefer mu.Unlock()\n\tisGroupedFun = fun\n}\n\n// AddGroupedIEType adds IE type(s) to the defaultGroupedIEMap.\n// This is useful when you want to add new IE types to the defaultGroupedIEMap.\n//\n// See also SetIsGroupedFun().\nfunc AddGroupedIEType(ts ...uint8) {\n\tmu.Lock()\n\tdefer mu.Unlock()\n\tfor _, t := range ts {\n\t\tdefaultGroupedIEMap[t] = true\n\t}\n}\n\n// IsGrouped reports whether an IE is grouped type or not.\n//\n// By default, this package determines if an IE is grouped type or not by checking\n// if the IE type is in the defaultGroupedIEMap.\n// You can change this entire behavior by calling SetIsGroupedFun(), or you can add\n// new IE types to the defaultGroupedIEMap by calling AddGroupedIEType().\nfunc (i *IE) IsGrouped() bool {\n\treturn isGroupedFun(i.Type)\n}\n\n// Add adds variable number of IEs to a grouped IE and update length of it.\n// This does nothing if the type of the IE is not grouped (no errors).\nfunc (i *IE) Add(ies ...*IE) {\n\tif !i.IsGrouped() {\n\t\treturn\n\t}\n\n\tfor _, ie := range ies {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\ti.ChildIEs = append(i.ChildIEs, ie)\n\n\t\tserialized, err := ie.Marshal()\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\ti.Payload = append(i.Payload, serialized...)\n\t}\n\ti.SetLength()\n}\n\n// Remove removes an IE looked up by type and instance.\nfunc (i *IE) Remove(typ, instance uint8) {\n\tif !i.IsGrouped() {\n\t\treturn\n\t}\n\n\ti.Payload = nil\n\tnewChildren := make([]*IE, len(i.ChildIEs))\n\tidx := 0\n\tfor _, ie := range i.ChildIEs {\n\t\tif ie.Type == typ && ie.Instance() == instance {\n\t\t\tnewChildren = newChildren[:len(newChildren)-1]\n\t\t\tcontinue\n\t\t}\n\t\tnewChildren[idx] = ie\n\t\tidx++\n\n\t\tserialized, err := ie.Marshal()\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\ti.Payload = append(i.Payload, serialized...)\n\t}\n\ti.ChildIEs = newChildren\n\ti.SetLength()\n}\n\n// FindByType returns IE looked up by type and instance.\n//\n// The program may be slower when calling this method multiple times\n// because this ranges over a ChildIEs each time it is called.\nfunc (i *IE) FindByType(typ, instance uint8) (*IE, error) {\n\tif !i.IsGrouped() {\n\t\treturn nil, ErrInvalidType\n\t}\n\n\tfor _, ie := range i.ChildIEs {\n\t\tif ie.Type == typ && ie.Instance() == instance {\n\t\t\treturn ie, nil\n\t\t}\n\t}\n\treturn nil, ErrIENotFound\n}\n"
  },
  {
    "path": "gtpv2/ie/ie_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie_test\n\nimport (\n\t\"net\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\nvar (\n\tmac1, _ = net.ParseMAC(\"12:34:56:78:90:01\")\n\tmac2, _ = net.ParseMAC(\"12:34:56:78:90:02\")\n)\n\nvar cases = []struct {\n\tdescription string\n\tstructured  *ie.IE\n\tserialized  []byte\n}{\n\t{\n\t\t\"IMSI\",\n\t\tie.NewIMSI(\"123451234567890\"),\n\t\t[]byte{0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0},\n\t}, {\n\t\t\"Cause\",\n\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t[]byte{0x02, 0x00, 0x02, 0x00, 0x10, 0x00},\n\t}, {\n\t\t\"CauseIMSIIMEINotKnown\",\n\t\tie.NewCause(gtpv2.CauseIMSIIMEINotKnown, 1, 0, 0, ie.NewIMSI(\"\")),\n\t\t[]byte{0x02, 0x00, 0x06, 0x00, 0x60, 0x04, 0x01, 0x00, 0x00, 0x00},\n\t}, {\n\t\t\"Recovery\",\n\t\tie.NewRecovery(0xff),\n\t\t[]byte{0x03, 0x00, 0x01, 0x00, 0xff},\n\t}, {\n\t\t\"AccessPointName\",\n\t\tie.NewAccessPointName(\"some.apn.example\"),\n\t\t[]byte{0x47, 0x00, 0x11, 0x00, 0x04, 0x73, 0x6f, 0x6d, 0x65, 0x03, 0x61, 0x70, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65},\n\t}, {\n\t\t\"AggregateMaximumBitRate\",\n\t\tie.NewAggregateMaximumBitRate(0x11111111, 0x22222222),\n\t\t[]byte{0x48, 0x00, 0x08, 0x00, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22},\n\t}, {\n\t\t\"EPSBearerID\",\n\t\tie.NewEPSBearerID(0x05),\n\t\t[]byte{0x49, 0x00, 0x01, 0x00, 0x05},\n\t}, {\n\t\t\"IPAddress/v4\",\n\t\tie.NewIPAddress(\"1.1.1.1\"),\n\t\t[]byte{0x4a, 0x00, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01},\n\t}, {\n\t\t\"IPAddress/v6\",\n\t\tie.NewIPAddress(\"2001::1\"),\n\t\t[]byte{0x4a, 0x00, 0x10, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},\n\t}, {\n\t\t\"MobileEquipmentIdentity\",\n\t\tie.NewMobileEquipmentIdentity(\"123450123456789\"),\n\t\t[]byte{0x4b, 0x00, 0x08, 0x00, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9},\n\t}, {\n\t\t\"MSISDN\",\n\t\tie.NewMSISDN(\"123450123456789\"),\n\t\t[]byte{0x4c, 0x00, 0x08, 0x00, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9},\n\t}, {\n\t\t\"Indication\",\n\t\tie.NewIndication(\n\t\t\t1, 0, 1, 0, 0, 0, 0, 1,\n\t\t\t0, 0, 0, 0, 1, 0, 0, 0,\n\t\t\t0, 0, 0, 1, 0, 1, 0, 1,\n\t\t\t0, 0, 0, 1, 0, 0, 0, 0,\n\t\t\t1, 0, 0, 0, 1, 0, 0, 0,\n\t\t\t1, 0, 0, 0, 0, 0, 0, 1,\n\t\t\t0, 1, 0, 0, 0, 0, 0, 0,\n\t\t\t1, 0, 1, 0, 0, 0, 0, 0,\n\t\t\t0, 0, 0, 0, 0, 0, 0, 1,\n\t\t),\n\t\t[]byte{0x4d, 0x00, 0x09, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40, 0xa0, 0x01},\n\t}, {\n\t\t\"IndicationFromBitSequence\",\n\t\tie.NewIndicationFromBitSequence(\"101000010000100000010101000100001000100010000001010000001010000000000001\"),\n\t\t[]byte{0x4d, 0x00, 0x09, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40, 0xa0, 0x01},\n\t}, {\n\t\t\"IndicationFromOctets/Full\",\n\t\tie.NewIndicationFromOctets(0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40, 0xa0, 0x01),\n\t\t[]byte{0x4d, 0x00, 0x09, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40, 0xa0, 0x01},\n\t}, {\n\t\t\"IndicationFromOctets/Short\",\n\t\tie.NewIndicationFromOctets(0xa1, 0x08),\n\t\t[]byte{0x4d, 0x00, 0x02, 0x00, 0xa1, 0x08},\n\t}, {\n\t\t\"ProtocolConfigurationOptions\",\n\t\tie.NewProtocolConfigurationOptions(\n\t\t\tgtpv2.ConfigProtocolPPPWithIP,\n\t\t\t// see pco-ppp_test.go for how to create these payload.\n\t\t\tie.NewPCOContainer(gtpv2.ProtoIDIPCP, []byte{0x01, 0x00, 0x00, 0x10, 0x03, 0x06, 0x01, 0x01, 0x01, 0x01, 0x81, 0x06, 0x02, 0x02, 0x02, 0x02}),\n\t\t\tie.NewPCOContainer(gtpv2.ProtoIDPAP, []byte{0x01, 0x00, 0x00, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x03, 0x62, 0x61, 0x72}),\n\t\t\tie.NewPCOContainer(gtpv2.ProtoIDCHAP, []byte{0x01, 0x00, 0x00, 0x0c, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x66, 0x6f, 0x6f}),\n\t\t\tie.NewPCOContainer(gtpv2.ContIDMSSupportOfNetworkRequestedBearerControlIndicator, nil),\n\t\t\tie.NewPCOContainer(gtpv2.ContIDIPAddressAllocationViaNASSignalling, nil),\n\t\t\tie.NewPCOContainer(gtpv2.ContIDDNSServerIPv4AddressRequest, nil),\n\t\t\tie.NewPCOContainer(gtpv2.ContIDIPv4LinkMTURequest, nil),\n\t\t),\n\t\t[]byte{\n\t\t\t0x4e, 0x00, 0x3e, 0x00,\n\t\t\t// Extension / ConfigurationProtocol\n\t\t\t0x80,\n\t\t\t// IPCP\n\t\t\t0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x03, 0x06, 0x01, 0x01, 0x01, 0x01, 0x81, 0x06, 0x02, 0x02, 0x02, 0x02,\n\t\t\t// PAP\n\t\t\t0xc0, 0x23, 0x0c, 0x01, 0x00, 0x00, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x03, 0x62, 0x61, 0x72,\n\t\t\t// CHAP\n\t\t\t0xc2, 0x23, 0x0c, 0x01, 0x00, 0x00, 0x0c, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x66, 0x6f, 0x6f,\n\t\t\t// Bearer control indicator\n\t\t\t0x00, 0x05, 0x00,\n\t\t\t// IP alloc via NAS\n\t\t\t0x00, 0x0a, 0x00,\n\t\t\t// DNS server request\n\t\t\t0x00, 0x0d, 0x00,\n\t\t\t// IPv4 link MTU request\n\t\t\t0x00, 0x10, 0x00,\n\t\t},\n\t}, {\n\t\t\"PDNAddressAllocation/v4\",\n\t\tie.NewPDNAddressAllocation(\"1.1.1.1\"),\n\t\t[]byte{0x4f, 0x00, 0x05, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01},\n\t}, {\n\t\t\"PDNAddressAllocation/v6\",\n\t\tie.NewPDNAddressAllocationIPv6(\"2001::1\", 64),\n\t\t[]byte{0x4f, 0x00, 0x12, 0x00, 0x02, 0x40, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},\n\t}, {\n\t\t\"PDNAddressAllocation/v4v6\",\n\t\tie.NewPDNAddressAllocationDual(\"1.1.1.1\", \"2001::1\", 64),\n\t\t[]byte{0x4f, 0x00, 0x16, 0x00, 0x03, 0x40, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01},\n\t}, {\n\t\t\"PDNAddressAllocation/NonIP\",\n\t\tie.NewPDNAddressAllocation(\"\"),\n\t\t[]byte{0x4f, 0x00, 0x01, 0x00, 0x04},\n\t}, {\n\t\t\"BearerQoS\",\n\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t[]byte{0x50, 0x00, 0x16, 0x00, 0x49, 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22},\n\t}, {\n\t\t\"FlowQoS\",\n\t\tie.NewFlowQoS(0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t[]byte{0x51, 0x00, 0x15, 0x00, 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22},\n\t}, {\n\t\t\"RATType\",\n\t\tie.NewRATType(gtpv2.RATTypeEUTRAN),\n\t\t[]byte{0x52, 0x00, 0x01, 0x00, 0x06},\n\t}, {\n\t\t\"ServingNetwork/2-digit\",\n\t\tie.NewServingNetwork(\"123\", \"45\"),\n\t\t[]byte{0x53, 0x00, 0x03, 0x00, 0x21, 0xf3, 0x54},\n\t}, {\n\t\t\"ServingNetwork/3-digit\",\n\t\tie.NewServingNetwork(\"123\", \"456\"),\n\t\t[]byte{0x53, 0x00, 0x03, 0x00, 0x21, 0x63, 0x54},\n\t}, {\n\t\t\"BearerTFT/TFTOpCreateNewTFT/NoParams\",\n\t\tie.NewBearerTFTCreateNewTFT(\n\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv4LocalAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), net.CIDRMask(64, 128),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6LocalAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFDownlinkOnly, 2, 0,\n\t\t\t\t\tie.NewTFTPFComponentProtocolIdentifierNextHeader(1),\n\t\t\t\t\tie.NewTFTPFComponentSingleLocalPort(2152),\n\t\t\t\t\tie.NewTFTPFComponentSingleRemotePort(2123),\n\t\t\t\t\tie.NewTFTPFComponentLocalPortRange(2123, 2152),\n\t\t\t\t\tie.NewTFTPFComponentRemotePortRange(2152, 2123),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFUplinkOnly, 3, 0,\n\t\t\t\t\tie.NewTFTPFComponentSecurityParameterIndex(0xdeadbeef),\n\t\t\t\t\tie.NewTFTPFComponentTypeOfServiceTrafficClass(1, 2),\n\t\t\t\t\tie.NewTFTPFComponentFlowLabel(0x00011111),\n\t\t\t\t\tie.NewTFTPFComponentDestinationMACAddress(mac1),\n\t\t\t\t\tie.NewTFTPFComponentSourceMACAddress(mac2),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFBidirectional, 4, 0,\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGVID(0x0111),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGVID(0x0222),\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGPCPDEI(3),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGPCPDEI(5),\n\t\t\t\t\tie.NewTFTPFComponentEthertype(0x0800),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnil,\n\t\t),\n\t\t[]byte{\n\t\t\t0x54, 0x00, 0x9d, 0x00, 0x24, 0x01, 0x00, 0x57, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff,\n\t\t\t0x00, 0x11, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,\n\t\t\t0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x01, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x23, 0x20, 0x01,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x12,\n\t\t\t0x00, 0x12, 0x30, 0x01, 0x40, 0x08, 0x68, 0x50, 0x08, 0x4b, 0x41, 0x08, 0x4b, 0x08, 0x68, 0x51,\n\t\t\t0x08, 0x68, 0x08, 0x4b, 0x23, 0x00, 0x1a, 0x60, 0xde, 0xad, 0xbe, 0xef, 0x70, 0x01, 0x02, 0x80,\n\t\t\t0x01, 0x11, 0x11, 0x81, 0x12, 0x34, 0x56, 0x78, 0x90, 0x01, 0x82, 0x12, 0x34, 0x56, 0x78, 0x90,\n\t\t\t0x02, 0x34, 0x00, 0x0d, 0x83, 0x01, 0x11, 0x84, 0x02, 0x22, 0x85, 0x03, 0x86, 0x05, 0x87, 0x08,\n\t\t\t0x00,\n\t\t},\n\t}, {\n\t\t\"BearerTFT/TFTOpCreateNewTFT/NoParams\",\n\t\tie.NewBearerTFTCreateNewTFT(\n\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv4LocalAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), net.CIDRMask(64, 128),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6LocalAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFDownlinkOnly, 2, 0,\n\t\t\t\t\tie.NewTFTPFComponentProtocolIdentifierNextHeader(1),\n\t\t\t\t\tie.NewTFTPFComponentSingleLocalPort(2152),\n\t\t\t\t\tie.NewTFTPFComponentSingleRemotePort(2123),\n\t\t\t\t\tie.NewTFTPFComponentLocalPortRange(2123, 2152),\n\t\t\t\t\tie.NewTFTPFComponentRemotePortRange(2152, 2123),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFUplinkOnly, 3, 0,\n\t\t\t\t\tie.NewTFTPFComponentSecurityParameterIndex(0xdeadbeef),\n\t\t\t\t\tie.NewTFTPFComponentTypeOfServiceTrafficClass(1, 2),\n\t\t\t\t\tie.NewTFTPFComponentFlowLabel(0x00011111),\n\t\t\t\t\tie.NewTFTPFComponentDestinationMACAddress(mac1),\n\t\t\t\t\tie.NewTFTPFComponentSourceMACAddress(mac2),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFBidirectional, 4, 0,\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGVID(0x0111),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGVID(0x0222),\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGPCPDEI(3),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGPCPDEI(5),\n\t\t\t\t\tie.NewTFTPFComponentEthertype(0x0800),\n\t\t\t\t),\n\t\t\t},\n\t\t\t[]*ie.TFTParameter{\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t\t},\n\t\t),\n\t\t[]byte{\n\t\t\t0x54, 0x00, 0xaf, 0x00, 0x34, 0x01, 0x00, 0x57, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff,\n\t\t\t0x00, 0x11, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,\n\t\t\t0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x01, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x23, 0x20, 0x01,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x12,\n\t\t\t0x00, 0x12, 0x30, 0x01, 0x40, 0x08, 0x68, 0x50, 0x08, 0x4b, 0x41, 0x08, 0x4b, 0x08, 0x68, 0x51,\n\t\t\t0x08, 0x68, 0x08, 0x4b, 0x23, 0x00, 0x1a, 0x60, 0xde, 0xad, 0xbe, 0xef, 0x70, 0x01, 0x02, 0x80,\n\t\t\t0x01, 0x11, 0x11, 0x81, 0x12, 0x34, 0x56, 0x78, 0x90, 0x01, 0x82, 0x12, 0x34, 0x56, 0x78, 0x90,\n\t\t\t0x02, 0x34, 0x00, 0x0d, 0x83, 0x01, 0x11, 0x84, 0x02, 0x22, 0x85, 0x03, 0x86, 0x05, 0x87, 0x08,\n\t\t\t0x00, 0x01, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x02, 0x04, 0x11, 0x11, 0x22, 0x22, 0x03, 0x04, 0x01,\n\t\t\t0x02, 0x03, 0x04,\n\t\t},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeleteExistingTFT/NoParams\",\n\t\tie.NewBearerTFTDeleteExistingTFT(),\n\t\t[]byte{0x54, 0x00, 0x01, 0x00, 0x40},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeleteExistingTFT/NoParams\",\n\t\tie.NewBearerTFTDeleteExistingTFT(),\n\t\t[]byte{0x54, 0x00, 0x01, 0x00, 0x40},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeleteExistingTFT/NoParams\",\n\t\tie.NewBearerTFTDeleteExistingTFT(),\n\t\t[]byte{0x54, 0x00, 0x01, 0x00, 0x40},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeleteExistingTFT/NoParams\",\n\t\tie.NewBearerTFTDeleteExistingTFT(),\n\t\t[]byte{0x54, 0x00, 0x01, 0x00, 0x40},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeleteExistingTFT/WithParams\",\n\t\tie.NewBearerTFTDeleteExistingTFT(\n\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t),\n\t\t[]byte{\n\t\t\t0x54, 0x00, 0x13, 0x00, 0x50,\n\t\t\t0x01, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t0x02, 0x04, 0x11, 0x11, 0x22, 0x22,\n\t\t\t0x03, 0x04, 0x01, 0x02, 0x03, 0x04,\n\t\t},\n\t}, {\n\t\t\"BearerTFT/TFTOpAddPacketFilters/NoParams\",\n\t\tie.NewBearerTFTAddPacketFilters(\n\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnil,\n\t\t),\n\t\t[]byte{\n\t\t\t0x54, 0x00, 0x0d, 0x00, 0x61,\n\t\t\t0x01, 0x00, 0x09, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00,\n\t\t},\n\t}, {\n\t\t\"BearerTFT/TFTOpReplacePacketFilters/NoParams\",\n\t\tie.NewBearerTFTReplacePacketFilters(\n\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnil,\n\t\t),\n\t\t[]byte{\n\t\t\t0x54, 0x00, 0x0d, 0x00, 0x81,\n\t\t\t0x01, 0x00, 0x09, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00,\n\t\t},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeletePacketFilters/NoParams\",\n\t\tie.NewBearerTFTDeletePacketFilters([]uint8{1, 2, 3, 4}, nil),\n\t\t[]byte{0x54, 0x00, 0x05, 0x00, 0xa4, 0x01, 0x02, 0x03, 0x04},\n\t}, {\n\t\t\"BearerTFT/TFTOpDeletePacketFilters/WithParams\",\n\t\tie.NewBearerTFTDeletePacketFilters(\n\t\t\t[]uint8{1, 2, 3, 4},\n\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t),\n\t\t[]byte{\n\t\t\t0x54, 0x00, 0x17, 0x00, 0xb4,\n\t\t\t0x01, 0x02, 0x03, 0x04,\n\t\t\t0x01, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t0x02, 0x04, 0x11, 0x11, 0x22, 0x22,\n\t\t\t0x03, 0x04, 0x01, 0x02, 0x03, 0x04,\n\t\t},\n\t}, {\n\t\t\"BearerTFT/TFTOpNoTFTOperation/NoParams\",\n\t\tie.NewBearerTFTNoTFTOperation(),\n\t\t[]byte{0x54, 0x00, 0x01, 0x00, 0xc0},\n\t}, {\n\t\t\"UserLocationInformation/Lazy-1\",\n\t\tie.NewUserLocationInformationLazy(\n\t\t\t\"123\", \"45\",\n\t\t\t0x1111, 0x2222, 0x3333, -1, 0x5555, 0x666666, -1, 0x22222222,\n\t\t),\n\t\t[]byte{\n\t\t\t0x56, 0x00, 0x26, 0x00,\n\t\t\t// Flags\n\t\t\t0xbb,\n\t\t\t// CGI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x22, 0x22,\n\t\t\t// SAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x33, 0x33,\n\t\t\t// TAI\n\t\t\t0x21, 0xf3, 0x54, 0x55, 0x55,\n\t\t\t// ECGI\n\t\t\t0x21, 0xf3, 0x54, 0x00, 0x06, 0x66, 0x66,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11,\n\t\t\t// Extended Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x22, 0x22, 0x22,\n\t\t},\n\t}, {\n\t\t\"UserLocationInformation/Lazy-2\",\n\t\tie.NewUserLocationInformationLazy(\n\t\t\t\"123\", \"45\",\n\t\t\t0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x666666, 0x11111111, 0x22222222,\n\t\t),\n\t\t[]byte{\n\t\t\t0x56, 0x00, 0x33, 0x00,\n\t\t\t// Flags\n\t\t\t0xff,\n\t\t\t// CGI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x22, 0x22,\n\t\t\t// SAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x33, 0x33,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x44, 0x44,\n\t\t\t// TAI\n\t\t\t0x21, 0xf3, 0x54, 0x55, 0x55,\n\t\t\t// ECGI\n\t\t\t0x21, 0xf3, 0x54, 0x00, 0x06, 0x66, 0x66,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11,\n\t\t\t// Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x11,\n\t\t\t// Extended Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x22, 0x22, 0x22,\n\t\t},\n\t}, {\n\t\t\"UserLocationInformation/Full\",\n\t\tie.NewUserLocationInformation(\n\t\t\t1, 1, 1, 1, 1, 1, 1, 1, \"123\", \"45\",\n\t\t\t0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x666666, 0x11111111, 0x22222222,\n\t\t),\n\t\t[]byte{\n\t\t\t0x56, 0x00, 0x33, 0x00,\n\t\t\t// Flags\n\t\t\t0xff,\n\t\t\t// CGI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x22, 0x22,\n\t\t\t// SAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x33, 0x33,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x44, 0x44,\n\t\t\t// TAI\n\t\t\t0x21, 0xf3, 0x54, 0x55, 0x55,\n\t\t\t// ECGI\n\t\t\t0x21, 0xf3, 0x54, 0x00, 0x06, 0x66, 0x66,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11,\n\t\t\t// Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x11,\n\t\t\t// Extended Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x22, 0x22, 0x22,\n\t\t},\n\t}, {\n\t\t\"UserLocationInformation/Full/v0.7.9+\",\n\t\tie.NewUserLocationInformationStruct(\n\t\t\tie.NewCGI(\"123\", \"45\", 0x1111, 0x2222),\n\t\t\tie.NewSAI(\"123\", \"45\", 0x1111, 0x3333),\n\t\t\tie.NewRAI(\"123\", \"45\", 0x1111, 0x4444),\n\t\t\tie.NewTAI(\"123\", \"45\", 0x5555),\n\t\t\tie.NewECGI(\"123\", \"45\", 0x66666666),\n\t\t\tie.NewLAI(\"123\", \"45\", 0x1111),\n\t\t\tie.NewMENBI(\"123\", \"45\", 0x11111111),\n\t\t\tie.NewEMENBI(\"123\", \"45\", 0x22222222),\n\t\t),\n\t\t[]byte{\n\t\t\t0x56, 0x00, 0x33, 0x00,\n\t\t\t// Flags\n\t\t\t0xff,\n\t\t\t// CGI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x22, 0x22,\n\t\t\t// SAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x33, 0x33,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x44, 0x44,\n\t\t\t// TAI\n\t\t\t0x21, 0xf3, 0x54, 0x55, 0x55,\n\t\t\t// ECGI\n\t\t\t0x21, 0xf3, 0x54, 0x06, 0x66, 0x66, 0x66,\n\t\t\t// RAI\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11,\n\t\t\t// Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x11,\n\t\t\t// Extended Macro eNB ID\n\t\t\t0x21, 0xf3, 0x54, 0x22, 0x22, 0x22,\n\t\t},\n\t}, {\n\t\t\"FullyQualifiedTEID/v4\",\n\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS11MMEGTPC, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t[]byte{0x57, 0x00, 0x09, 0x00, 0x8a, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01},\n\t}, {\n\t\t\"FullyQualifiedTEID/v6\",\n\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS11MMEGTPC, 0xffffffff, \"\", \"2001::1\"),\n\t\t[]byte{0x57, 0x00, 0x15, 0x00, 0x4a, 0xff, 0xff, 0xff, 0xff, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},\n\t}, {\n\t\t\"FullyQualifiedTEID/v4v6\",\n\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS11MMEGTPC, 0xffffffff, \"1.1.1.1\", \"2001::1\"),\n\t\t[]byte{0x57, 0x00, 0x19, 0x00, 0xca, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},\n\t}, {\n\t\t\"TMSI\",\n\t\tie.NewTMSI(0xffffffff),\n\t\t[]byte{0x58, 0x00, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff},\n\t}, {\n\t\t\"GlobalCNID\",\n\t\tie.NewGlobalCNID(\"123\", \"45\", 0xfff),\n\t\t[]byte{0x59, 0x00, 0x05, 0x00, 0x21, 0xf3, 0x54, 0x0f, 0xff},\n\t}, {\n\t\t\"S103PDNDataForwardingInfo/v4\",\n\t\tie.NewS103PDNDataForwardingInfo(\"1.1.1.1\", 0xdeadbeef, 5, 6, 7),\n\t\t[]byte{0x5a, 0x00, 0x0d, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, 0xde, 0xad, 0xbe, 0xef, 0x03, 0x05, 0x06, 0x07},\n\t}, {\n\t\t\"S103PDNDataForwardingInfo/v6\",\n\t\tie.NewS103PDNDataForwardingInfo(\"2001::1\", 0xdeadbeef, 5, 6, 7),\n\t\t[]byte{0x5a, 0x00, 0x19, 0x00, 0x10, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0xbe, 0xef, 0x03, 0x05, 0x06, 0x07},\n\t}, {\n\t\t\"S1UDataForwarding/v4\",\n\t\tie.NewS1UDataForwarding(5, \"1.1.1.1\", 0xdeadbeef),\n\t\t[]byte{0x5b, 0x00, 0x0a, 0x00, 0x05, 0x04, 0x01, 0x01, 0x01, 0x01, 0xde, 0xad, 0xbe, 0xef},\n\t}, {\n\t\t\"S1UDataForwarding/v6\",\n\t\tie.NewS1UDataForwarding(5, \"2001::1\", 0xdeadbeef),\n\t\t[]byte{0x5b, 0x00, 0x16, 0x00, 0x05, 0x10, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0xbe, 0xef},\n\t}, {\n\t\t\"DelayValue\",\n\t\tie.NewDelayValue(500 * time.Millisecond),\n\t\t[]byte{0x5c, 0x00, 0x01, 0x00, 0x0a},\n\t}, {\n\t\t\"BearerContext\",\n\t\tie.NewBearerContext(ie.NewDelayValue(500*time.Millisecond), ie.NewDelayValue(100*time.Millisecond)),\n\t\t[]byte{0x5d, 0x00, 0x0a, 0x00, 0x5c, 0x00, 0x01, 0x00, 0x0a, 0x5c, 0x00, 0x01, 0x00, 0x02},\n\t}, {\n\t\t\"ChargingID\",\n\t\tie.NewChargingID(0xffffffff),\n\t\t[]byte{0x5e, 0x00, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff},\n\t}, {\n\t\t\"ChargingCharacteristics\",\n\t\tie.NewChargingCharacteristics(0xffff),\n\t\t[]byte{0x5f, 0x00, 0x02, 0x00, 0xff, 0xff},\n\t}, {\n\t\t\"BearerFlags\",\n\t\tie.NewBearerFlags(1, 1, 1, 1),\n\t\t[]byte{0x61, 0x00, 0x01, 0x00, 0x0f},\n\t}, {\n\t\t\"PDNType\",\n\t\tie.NewPDNType(gtpv2.PDNTypeIPv4),\n\t\t[]byte{0x63, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"ProcedureTransactionID\",\n\t\tie.NewProcedureTransactionID(1),\n\t\t[]byte{0x64, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"PacketTMSI\",\n\t\tie.NewPacketTMSI(0xdeadbeef),\n\t\t[]byte{0x6f, 0x00, 0x04, 0x00, 0xde, 0xad, 0xbe, 0xef},\n\t}, {\n\t\t\"PTMSISignature\",\n\t\tie.NewPTMSISignature(0xbeebee),\n\t\t[]byte{0x70, 0x00, 0x03, 0x00, 0xbe, 0xeb, 0xee},\n\t}, {\n\t\t\"HopCounter\",\n\t\tie.NewHopCounter(1),\n\t\t[]byte{0x71, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"UETimeZone\",\n\t\tie.NewUETimeZone(9*time.Hour, 0),\n\t\t[]byte{0x72, 0x00, 0x02, 0x00, 0x63, 0x00},\n\t}, {\n\t\t\"UETimeZone\",\n\t\tie.NewUETimeZone(2*time.Hour, 0),\n\t\t[]byte{0x72, 0x00, 0x02, 0x00, 0x80, 0x00},\n\t}, {\n\t\t\"TraceReference\",\n\t\tie.NewTraceReference(\"123\", \"45\", 1),\n\t\t[]byte{0x73, 0x00, 0x06, 0x00, 0x21, 0xf3, 0x54, 0x00, 0x00, 0x01},\n\t}, {\n\t\t\"GUTI\",\n\t\tie.NewGUTI(\"123\", \"45\", 0x1111, 0x22, 0x33333333),\n\t\t[]byte{0x75, 0x00, 0x0a, 0x00, 0x21, 0xf3, 0x54, 0x11, 0x11, 0x22, 0x33, 0x33, 0x33, 0x33},\n\t}, {\n\t\t\"PLMNID/2digits\",\n\t\tie.NewPLMNID(\"123\", \"45\"),\n\t\t[]byte{0x78, 0x00, 0x03, 0x00, 0x21, 0xf3, 0x54},\n\t}, {\n\t\t\"PLMNID/3digits\",\n\t\tie.NewPLMNID(\"123\", \"456\"),\n\t\t[]byte{0x78, 0x00, 0x03, 0x00, 0x21, 0x63, 0x54},\n\t}, {\n\t\t\"PortNumber\",\n\t\tie.NewPortNumber(2123),\n\t\t[]byte{0x7e, 0x00, 0x02, 0x00, 0x08, 0x4b},\n\t}, {\n\t\t\"APNRestriction\",\n\t\tie.NewAPNRestriction(gtpv2.APNRestrictionPublic1),\n\t\t[]byte{0x7f, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"SelectionMode\",\n\t\tie.NewSelectionMode(gtpv2.SelectionModeMSProvidedAPNSubscriptionNotVerified),\n\t\t[]byte{0x80, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"FullyQualifiedCSID/v4\",\n\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1),\n\t\t[]byte{0x84, 0x00, 0x07, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"FullyQualifiedCSID/v4/multiCSIDs\",\n\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1, 2),\n\t\t[]byte{0x84, 0x00, 0x09, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x02},\n\t}, {\n\t\t\"FullyQualifiedCSID/v6\",\n\t\tie.NewFullyQualifiedCSID(\"2001::1\", 1),\n\t\t[]byte{0x84, 0x00, 0x13, 0x00, 0x11, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"FullyQualifiedCSID/other\",\n\t\tie.NewFullyQualifiedCSID(\"12304501\", 1),\n\t\t[]byte{0x84, 0x00, 0x07, 0x00, 0x21, 0x12, 0x30, 0x45, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"NodeType\",\n\t\tie.NewNodeType(gtpv2.NodeTypeMME),\n\t\t[]byte{0x87, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"FullyQualifiedDomainName\",\n\t\tie.NewFullyQualifiedDomainName(\"some-fqdn.example\"),\n\t\t[]byte{0x88, 0x00, 0x12, 0x00, 0x09, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x66, 0x71, 0x64, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65},\n\t}, {\n\t\t\"RFSPIndex\",\n\t\tie.NewRFSPIndex(1),\n\t\t[]byte{0x90, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"UserCSGInformation\",\n\t\tie.NewUserCSGInformation(\"123\", \"45\", 0x00ffffff, gtpv2.AccessModeHybrid, 0, gtpv2.CMICSG),\n\t\t[]byte{0x91, 0x00, 0x08, 0x00, 0x21, 0xf3, 0x54, 0x00, 0xff, 0xff, 0xff, 0x41},\n\t}, {\n\t\t\"CSGID\",\n\t\tie.NewCSGID(0x00ffffff),\n\t\t[]byte{0x93, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0xff},\n\t}, {\n\t\t\"CSGMembershipIndication\",\n\t\tie.NewCSGMembershipIndication(gtpv2.CMICSG),\n\t\t[]byte{0x94, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"ServiceIndicator\",\n\t\tie.NewServiceIndicator(gtpv2.ServiceIndCSCall),\n\t\t[]byte{0x95, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"DetachType\",\n\t\tie.NewDetachType(gtpv2.DetachTypePS),\n\t\t[]byte{0x96, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"LocalDistinguishedName\",\n\t\tie.NewLocalDistinguishedName(\"some-name\"),\n\t\t[]byte{0x97, 0x00, 0x09, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x6e, 0x61, 0x6d, 0x65},\n\t}, {\n\t\t\"NodeFeatures\",\n\t\tie.NewNodeFeatures(0x01),\n\t\t[]byte{0x98, 0x00, 0x01, 0x00, 0x01},\n\t}, {\n\t\t\"Throttling\",\n\t\tie.NewThrottling(20*time.Hour, 80),\n\t\t[]byte{0x9a, 0x00, 0x02, 0x00, 0x82, 0x50},\n\t}, {\n\t\t\"AllocationRetensionPriority\",\n\t\tie.NewAllocationRetensionPriority(1, 2, 1),\n\t\t[]byte{0x9b, 0x00, 0x01, 0x00, 0x49},\n\t}, {\n\t\t\"EPCTimer\",\n\t\tie.NewEPCTimer(20 * time.Hour),\n\t\t[]byte{0x9c, 0x00, 0x01, 0x00, 0x82},\n\t}, {\n\t\t\"ULITimestamp\",\n\t\tie.NewULITimestamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),\n\t\t[]byte{0xaa, 0x00, 0x04, 0x00, 0xdf, 0xd5, 0x2c, 0x00},\n\t}, {\n\t\t\"MBMSFlags\",\n\t\tie.NewMBMSFlags(1, 1),\n\t\t[]byte{0xab, 0x00, 0x01, 0x00, 0x03},\n\t}, {\n\t\t\"RANNASCause\",\n\t\tie.NewRANNASCause(gtpv2.ProtoTypeS1APCause, gtpv2.CauseTypeNAS, []byte{0x01}),\n\t\t[]byte{0xac, 0x00, 0x02, 0x00, 0x12, 0x01},\n\t}, {\n\t\t\"PagingAndServiceInformation\",\n\t\tie.NewPagingAndServiceInformation(5, 0x01, 0xff),\n\t\t[]byte{0xba, 0x00, 0x03, 0x00, 0x05, 0x01, 0x7f},\n\t}, {\n\t\t\"IntegerNumber\",\n\t\tie.NewIntegerNumber(2020),\n\t\t[]byte{0xbb, 0x00, 0x02, 0x00, 0x07, 0xe4},\n\t}, {\n\t\t\"PrivateExtension\",\n\t\tie.NewPrivateExtension(10415, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t[]byte{0xff, 0x00, 0x06, 0x00, 0x28, 0xaf, 0xde, 0xad, 0xbe, 0xef},\n\t},\n}\n\nfunc TestIEs(t *testing.T) {\n\tfor _, c := range cases {\n\t\tt.Run(\"marshal/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"unmarshal/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.Parse(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\topt := cmp.AllowUnexported(*got, *c.structured)\n\t\t\tif diff := cmp.Diff(got, c.structured, opt); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestIEAddRemove(t *testing.T) {\n\ti := ie.NewBearerContext(\n\t\tie.NewIMSI(\"123451234567890\").WithInstance(1),\n\t\tie.NewMSISDN(\"819012345678\"),\n\t)\n\ti.Add(ie.NewAccessPointName(\"foo.example\"))\n\ti.Add(nil) // ignored\n\n\tadded := ie.NewBearerContext(\n\t\tie.NewIMSI(\"123451234567890\").WithInstance(1),\n\t\tie.NewMSISDN(\"819012345678\"),\n\t\tie.NewAccessPointName(\"foo.example\"),\n\t)\n\n\topt := cmp.AllowUnexported(*i, *added)\n\tif diff := cmp.Diff(i, added, opt); diff != \"\" {\n\t\tt.Error(diff)\n\t}\n\n\ti.Remove(ie.IMSI, 1)\n\n\tremoved := ie.NewBearerContext(\n\t\tie.NewMSISDN(\"819012345678\"),\n\t\tie.NewAccessPointName(\"foo.example\"),\n\t)\n\n\topt = cmp.AllowUnexported(*i, *removed)\n\tif diff := cmp.Diff(i, removed, opt); diff != \"\" {\n\t\tt.Error(diff)\n\t}\n}\n"
  },
  {
    "path": "gtpv2/ie/imsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewIMSI creates a new IMSI IE.\nfunc NewIMSI(imsi string) *IE {\n\ti, err := utils.StrToSwappedBytes(imsi, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(IMSI, 0x00, i)\n}\n\n// IMSI returns IMSI in string if the type of IE matches.\nfunc (i *IE) IMSI() (string, error) {\n\tif i.Type != IMSI {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.SwappedBytesToStr(i.Payload, true), nil\n}\n\n// MustIMSI returns IMSI in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIMSI() string {\n\tv, _ := i.IMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/indication.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"strconv\"\n)\n\n// TODO: add setters\n// TODO: consider using struct?\n\n// NewIndication creates a new Indication IE.\n// Note that each parameters should be 0 if false and 1 if true. Otherwise,\n// the value won't be set as expected in the bitwise operations.\nfunc NewIndication(\n\tdaf, dtf, hi, dfi, oi, isrsi, israi, sgwci,\n\tsqci, uimsi, cfsi, crsi, ps, pt, si, msv,\n\tretLoc, pbic, srni, s6af, s4af, mbmdt, israu, ccrsi,\n\tcprai, arrl, ppoff, ppon, ppsi, csfbi, clii, cpsr,\n\tnsi, uasi, dtci, bdwi, psci, pcri, aosi, aopi,\n\troaai, epcosi, cpopci, pmtmsi, s11tf, pnsi, unaccsi, wpmsi,\n\tfgsnn26, reprefi, fgsiwk, eevrsi, ltemui, ltempi, enbcrsi, tspcmi,\n\tcsrmfi, mtedtn, mtedta, n5gnmi, fgcnrs, fgcnri, fsrhoi, ethpdn,\n\tsp98, sp97, sp96, sp95, sp94, sp93, sp92, emci uint8,\n) *IE {\n\ti := New(Indication, 0x00, make([]byte, 9))\n\ti.Payload[0] |= sgwci\n\ti.Payload[0] |= (israi << 1)\n\ti.Payload[0] |= (isrsi << 2)\n\ti.Payload[0] |= (oi << 3)\n\ti.Payload[0] |= (dfi << 4)\n\ti.Payload[0] |= (hi << 5)\n\ti.Payload[0] |= (dtf << 6)\n\ti.Payload[0] |= (daf << 7)\n\n\ti.Payload[1] |= msv\n\ti.Payload[1] |= (si << 1)\n\ti.Payload[1] |= (pt << 2)\n\ti.Payload[1] |= (ps << 3)\n\ti.Payload[1] |= (crsi << 4)\n\ti.Payload[1] |= (cfsi << 5)\n\ti.Payload[1] |= (uimsi << 6)\n\ti.Payload[1] |= (sqci << 7)\n\n\ti.Payload[2] |= ccrsi\n\ti.Payload[2] |= (israu << 1)\n\ti.Payload[2] |= (mbmdt << 2)\n\ti.Payload[2] |= (s4af << 3)\n\ti.Payload[2] |= (s6af << 4)\n\ti.Payload[2] |= (srni << 5)\n\ti.Payload[2] |= (pbic << 6)\n\ti.Payload[2] |= (retLoc << 7)\n\n\ti.Payload[3] |= cpsr\n\ti.Payload[3] |= (clii << 1)\n\ti.Payload[3] |= (csfbi << 2)\n\ti.Payload[3] |= (ppsi << 3)\n\ti.Payload[3] |= (ppon << 4)\n\ti.Payload[3] |= (ppoff << 5)\n\ti.Payload[3] |= (arrl << 6)\n\ti.Payload[3] |= (cprai << 7)\n\n\ti.Payload[4] |= aopi\n\ti.Payload[4] |= (aosi << 1)\n\ti.Payload[4] |= (pcri << 2)\n\ti.Payload[4] |= (psci << 3)\n\ti.Payload[4] |= (bdwi << 4)\n\ti.Payload[4] |= (dtci << 5)\n\ti.Payload[4] |= (uasi << 6)\n\ti.Payload[4] |= (nsi << 7)\n\n\ti.Payload[5] |= wpmsi\n\ti.Payload[5] |= (unaccsi << 1)\n\ti.Payload[5] |= (pnsi << 2)\n\ti.Payload[5] |= (s11tf << 3)\n\ti.Payload[5] |= (pmtmsi << 4)\n\ti.Payload[5] |= (cpopci << 5)\n\ti.Payload[5] |= (epcosi << 6)\n\ti.Payload[5] |= (roaai << 7)\n\n\ti.Payload[6] |= tspcmi\n\ti.Payload[6] |= (enbcrsi << 1)\n\ti.Payload[6] |= (ltempi << 2)\n\ti.Payload[6] |= (ltemui << 3)\n\ti.Payload[6] |= (eevrsi << 4)\n\ti.Payload[6] |= (fgsiwk << 5)\n\ti.Payload[6] |= (reprefi << 6)\n\ti.Payload[6] |= (fgsnn26 << 7)\n\n\ti.Payload[7] |= ethpdn\n\ti.Payload[7] |= (fsrhoi << 1)\n\ti.Payload[7] |= (fgcnri << 2)\n\ti.Payload[7] |= (fgcnrs << 3)\n\ti.Payload[7] |= (n5gnmi << 4)\n\ti.Payload[7] |= (mtedta << 5)\n\ti.Payload[7] |= (mtedtn << 6)\n\ti.Payload[7] |= (csrmfi << 7)\n\n\ti.Payload[8] |= emci\n\ti.Payload[8] |= (sp92 << 1)\n\ti.Payload[8] |= (sp93 << 2)\n\ti.Payload[8] |= (sp94 << 3)\n\ti.Payload[8] |= (sp95 << 4)\n\ti.Payload[8] |= (sp96 << 5)\n\ti.Payload[8] |= (sp97 << 6)\n\ti.Payload[8] |= (sp98 << 7)\n\treturn i\n}\n\n// NewIndicationFromBitSequence creates a new Indication IE from string-formatted\n// sequence of bits. The sequence should look the same as Wireshark appearance.\n// The input is to be like \"101000010000100000010101000100001000100010000001010000001010000000000001\".\nfunc NewIndicationFromBitSequence(bitSequence string) *IE {\n\tif len(bitSequence) != 72 {\n\t\treturn nil\n\t}\n\n\tie := New(Indication, 0x00, make([]byte, 9))\n\tfor i, r := range bitSequence {\n\t\tbit, err := strconv.Atoi(string(r))\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tif bit > 1 {\n\t\t\tbit = 1\n\t\t}\n\n\t\t// index:\n\t\t//   0 =< i < 8 : set bits in first octet\n\t\t//   8 =< i < 16: set bits in second octet ...\n\t\t// bit shift:\n\t\t//   0 =< i < 8 : shift i to left\n\t\t//   8 =< i < 16: shift i - 8 to left ...\n\t\tie.Payload[i/8] |= uint8(bit << uint8(8*(i/8+1)-i-1))\n\t}\n\n\treturn ie\n}\n\n// NewIndicationFromOctets creates a new IndicationFromOctets IE from the set of octets.\nfunc NewIndicationFromOctets(octs ...uint8) *IE {\n\tie := New(Indication, 0x00, make([]byte, 0))\n\tfor i, o := range octs {\n\t\tif i >= 9 {\n\t\t\tbreak\n\t\t}\n\t\tie.Payload = append(ie.Payload, o)\n\t}\n\tie.SetLength()\n\treturn ie\n}\n\n// Indication returns Indication flags in []byte if the type of IE matches.\nfunc (i *IE) Indication() ([]byte, error) {\n\tif i.Type != Indication {\n\t\treturn nil, &InvalidTypeError{i.Type}\n\t}\n\n\treturn i.Payload, nil\n}\n\n// HasSGWCI reports whether an IE has SGWCI bit.\nfunc (i *IE) HasSGWCI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[0])\n}\n\n// HasISRAI reports whether an IE has ISRAI bit.\nfunc (i *IE) HasISRAI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[0])\n}\n\n// HasISRSI reports whether an IE has ISRSI bit.\nfunc (i *IE) HasISRSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[0])\n}\n\n// HasOI reports whether an IE has OI bit.\nfunc (i *IE) HasOI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[0])\n}\n\n// HasDFI reports whether an IE has DFI bit.\nfunc (i *IE) HasDFI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[0])\n}\n\n// HasHI reports whether an IE has HI bit.\nfunc (i *IE) HasHI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[0])\n}\n\n// HasDTF reports whether an IE has DTF bit.\nfunc (i *IE) HasDTF() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[0])\n}\n\n// HasDAF reports whether an IE has DAF bit.\nfunc (i *IE) HasDAF() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 1 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[0])\n}\n\n// HasMSV reports whether an IE has MSV bit.\nfunc (i *IE) HasMSV() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[1])\n}\n\n// HasSI reports whether an IE has SI bit.\nfunc (i *IE) HasSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[1])\n}\n\n// HasPT reports whether an IE has PT bit.\nfunc (i *IE) HasPT() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[1])\n}\n\n// HasPS reports whether an IE has PS bit.\nfunc (i *IE) HasPS() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[1])\n}\n\n// HasCRSI reports whether an IE has CRSI bit.\nfunc (i *IE) HasCRSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[1])\n}\n\n// HasCFSI reports whether an IE has CFSI bit.\nfunc (i *IE) HasCFSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[1])\n}\n\n// HasUIMSI reports whether an IE has UIMSI bit.\nfunc (i *IE) HasUIMSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[1])\n}\n\n// HasSQCI reports whether an IE has SQCI bit.\nfunc (i *IE) HasSQCI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 2 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[1])\n}\n\n// HasCCRSI reports whether an IE has CCRSI bit.\nfunc (i *IE) HasCCRSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[2])\n}\n\n// HasISRAU reports whether an IE has ISRAU bit.\nfunc (i *IE) HasISRAU() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[2])\n}\n\n// HasMBMDT reports whether an IE has MBMDT bit.\nfunc (i *IE) HasMBMDT() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[2])\n}\n\n// HasS4AF reports whether an IE has S4AF bit.\nfunc (i *IE) HasS4AF() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[2])\n}\n\n// HasS6AF reports whether an IE has S6AF bit.\nfunc (i *IE) HasS6AF() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[2])\n}\n\n// HasSRNI reports whether an IE has SRNI bit.\nfunc (i *IE) HasSRNI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[2])\n}\n\n// HasPBIC reports whether an IE has PBIC bit.\nfunc (i *IE) HasPBIC() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[2])\n}\n\n// HasRETLOC reports whether an IE has RETLOC bit.\nfunc (i *IE) HasRETLOC() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 3 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[2])\n}\n\n// HasCPSR reports whether an IE has CPSR bit.\nfunc (i *IE) HasCPSR() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[3])\n}\n\n// HasCLII reports whether an IE has CLII bit.\nfunc (i *IE) HasCLII() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[3])\n}\n\n// HasCSFBI reports whether an IE has CSFBI bit.\nfunc (i *IE) HasCSFBI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[3])\n}\n\n// HasPPSI reports whether an IE has PPSI bit.\nfunc (i *IE) HasPPSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[3])\n}\n\n// HasPPON reports whether an IE has PPON bit.\nfunc (i *IE) HasPPON() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[3])\n}\n\n// HasPPOF reports whether an IE has PPOF bit.\nfunc (i *IE) HasPPOF() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[3])\n}\n\n// HasARRL reports whether an IE has ARRL bit.\nfunc (i *IE) HasARRL() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[3])\n}\n\n// HasCPRAI reports whether an IE has CPRAI bit.\nfunc (i *IE) HasCPRAI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 4 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[3])\n}\n\n// HasAOPI reports whether an IE has AOPI bit.\nfunc (i *IE) HasAOPI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[4])\n}\n\n// HasAOSI reports whether an IE has AOSI bit.\nfunc (i *IE) HasAOSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[4])\n}\n\n// HasPCRI reports whether an IE has PCRI bit.\nfunc (i *IE) HasPCRI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[4])\n}\n\n// HasPSCI reports whether an IE has PSCI bit.\nfunc (i *IE) HasPSCI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[4])\n}\n\n// HasBDWI reports whether an IE has BDWI bit.\nfunc (i *IE) HasBDWI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[4])\n}\n\n// HasDTCI reports whether an IE has DTCI bit.\nfunc (i *IE) HasDTCI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[4])\n}\n\n// HasUASI reports whether an IE has UASI bit.\nfunc (i *IE) HasUASI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[4])\n}\n\n// HasNSI reports whether an IE has NSI bit.\nfunc (i *IE) HasNSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 5 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[4])\n}\n\n// HasWPMSI reports whether an IE has WPMSI bit.\nfunc (i *IE) HasWPMSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[5])\n}\n\n// HasUNACCSI reports whether an IE has UNACCSI bit.\nfunc (i *IE) HasUNACCSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[5])\n}\n\n// HasPNSI reports whether an IE has PNSI bit.\nfunc (i *IE) HasPNSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[5])\n}\n\n// HasS11TF reports whether an IE has S11TF bit.\nfunc (i *IE) HasS11TF() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[5])\n}\n\n// HasPMTMSI reports whether an IE has PMTMSI bit.\nfunc (i *IE) HasPMTMSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[5])\n}\n\n// HasCPOPCI reports whether an IE has CPOPCI bit.\nfunc (i *IE) HasCPOPCI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[5])\n}\n\n// HasEPCOSI reports whether an IE has EPCOSI bit.\nfunc (i *IE) HasEPCOSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[5])\n}\n\n// HasROAAI reports whether an IE has ROAAI bit.\nfunc (i *IE) HasROAAI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 6 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[5])\n}\n\n// HasTSPCMI reports whether an IE has TSPCMI bit.\nfunc (i *IE) HasTSPCMI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[6])\n}\n\n// HasENBCRSI reports whether an IE has ENBCRSI bit.\nfunc (i *IE) HasENBCRSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[6])\n}\n\n// HasLTEMPI reports whether an IE has LTEMPI bit.\nfunc (i *IE) HasLTEMPI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[6])\n}\n\n// HasLTEMUI reports whether an IE has LTEMUI bit.\nfunc (i *IE) HasLTEMUI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[6])\n}\n\n// HasEEVRSI reports whether an IE has EEVRSI bit.\nfunc (i *IE) HasEEVRSI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[6])\n}\n\n// Has5GSIWK reports whether an IE has 5GSIWK bit.\nfunc (i *IE) Has5GSIWK() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[6])\n}\n\n// HasREPREFI reports whether an IE has REPREFI bit.\nfunc (i *IE) HasREPREFI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[6])\n}\n\n// Has5GSNN26 reports whether an IE has 5GSNN26 bit.\nfunc (i *IE) Has5GSNN26() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 7 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[6])\n}\n\n// HasETHPDN reports whether an IE has ETHPDN bit.\nfunc (i *IE) HasETHPDN() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[7])\n}\n\n// Has5SRHOI reports whether an IE has 5SRHOI bit.\nfunc (i *IE) Has5SRHOI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v[7])\n}\n\n// Has5GCNRI reports whether an IE has 5GCNRI bit.\nfunc (i *IE) Has5GCNRI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v[7])\n}\n\n// Has5GCNRS reports whether an IE has 5GCNRS bit.\nfunc (i *IE) Has5GCNRS() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v[7])\n}\n\n// HasN5GNMI reports whether an IE has N5GNMI bit.\nfunc (i *IE) HasN5GNMI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v[7])\n}\n\n// HasMTEDTA reports whether an IE has MTEDTA bit.\nfunc (i *IE) HasMTEDTA() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v[7])\n}\n\n// HasMTEDTN reports whether an IE has MTEDTN bit.\nfunc (i *IE) HasMTEDTN() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v[7])\n}\n\n// HasCSRMFI reports whether an IE has CSRMFI bit.\nfunc (i *IE) HasCSRMFI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 8 {\n\t\treturn false\n\t}\n\n\treturn has8thBit(v[7])\n}\n\n// HasEMCI reports whether an IE has EMCI bit.\nfunc (i *IE) HasEMCI() bool {\n\tv, err := i.Indication()\n\tif err != nil {\n\t\treturn false\n\t}\n\tif len(v) < 9 {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v[8])\n}\n"
  },
  {
    "path": "gtpv2/ie/integer-number.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewIntegerNumber creates a new IntegerNumber IE.\nfunc NewIntegerNumber(num uint16) *IE {\n\treturn NewUint16IE(IntegerNumber, num)\n}\n\n// IntegerNumber returns IntegerNumber in uint16 if the type of IE matches.\nfunc (i *IE) IntegerNumber() (uint16, error) {\n\tswitch i.Type {\n\tcase IntegerNumber:\n\t\treturn i.ValueAsUint16()\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustIntegerNumber returns IntegerNumber in uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIntegerNumber() uint16 {\n\tv, _ := i.IntegerNumber()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/ip-addr.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// NewIPAddress creates a new IPAddress IE from string.\nfunc NewIPAddress(addr string) *IE {\n\tip := net.ParseIP(addr)\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn New(IPAddress, 0x00, v4)\n\t}\n\t// IPv6\n\treturn New(IPAddress, 0x00, ip)\n}\n\n// NewIPAddressNetIP creates a new IPAddress IE from net.IP.\nfunc NewIPAddressNetIP(ip net.IP) *IE {\n\tif v := ip.To4(); v != nil {\n\t\treturn New(IPAddress, 0x00, v)\n\t}\n\n\tif v := ip.To16(); v != nil {\n\t\treturn New(IPAddress, 0x00, v)\n\t}\n\n\t// return IE w/ \"something\" anyway, to avoid crash\n\treturn New(IPAddress, 0x00, ip)\n}\n\n// IPAddress returns IPAddress value if the type of IE matches.\nfunc (i *IE) IPAddress() (string, error) {\n\tip, err := i.IP()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn ip.String(), nil\n}\n\n// MustIPAddress returns IPAddress in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIPAddress() string {\n\tv, _ := i.IPAddress()\n\treturn v\n}\n\n// IP returns IP value in net.IP if the type of IE matches.\n//\n// This does not validate the values. Even if the IP address fields in an\n// IE contains some invalid byte sequence, it just try to return as it is.\n// To retrieve only if it's valid, use IPv4 or IPv6 instead.\n//\n// If the IE has both IPv4 and IPv6, this returns IPv4. To retrieve IPv6\n// value in that case, use IPv6() instead.\nfunc (i *IE) IP() (net.IP, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase IPAddress:\n\t\treturn net.IP(i.Payload), nil\n\tcase PDNAddressAllocation:\n\t\tif len(i.Payload) < 5 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\tpaa, err := ParsePDNAddressAllocationFields(i.Payload)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tswitch paa.PDNType {\n\t\tcase pdnTypeIPv4, pdnTypeIPv4v6:\n\t\t\treturn paa.IPv4Address, nil\n\t\tcase pdnTypeIPv6:\n\t\t\treturn paa.IPv6Address, nil\n\t\tdefault:\n\t\t\treturn nil, ErrIEValueNotFound\n\t\t}\n\tcase S103PDNDataForwardingInfo:\n\t\tswitch i.Payload[0] {\n\t\tcase 4:\n\t\t\tif len(i.Payload) < 5 {\n\t\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn net.IP(i.Payload[1:5]), nil\n\t\tcase 16:\n\t\t\tif len(i.Payload) < 17 {\n\t\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn net.IP(i.Payload[1:17]), nil\n\t\tdefault:\n\t\t\treturn nil, ErrMalformed\n\t\t}\n\tcase S1UDataForwarding:\n\t\tswitch i.Payload[1] {\n\t\tcase 4:\n\t\t\tif len(i.Payload) < 6 {\n\t\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn net.IP(i.Payload[2:6]), nil\n\t\tcase 16:\n\t\t\tif len(i.Payload) < 18 {\n\t\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t\t}\n\t\t\treturn net.IP(i.Payload[2:18]), nil\n\t\tdefault:\n\t\t\treturn nil, ErrMalformed\n\t\t}\n\tcase FullyQualifiedTEID:\n\t\tfteid, err := ParseFullyQualifiedTEIDFields(i.Payload)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif i.HasIPv4() {\n\t\t\treturn fteid.IPv4Address, nil\n\t\t} else if i.HasIPv6() {\n\t\t\treturn fteid.IPv6Address, nil\n\t\t}\n\t\treturn nil, ErrIEValueNotFound\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustIP returns IP in net.IP, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIP() net.IP {\n\tv, _ := i.IP()\n\treturn v\n}\n\n// IPv4 returns IPv4 value in net.IP if the type of IE matches.\nfunc (i *IE) IPv4() (net.IP, error) {\n\tip, err := i.IP()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif v := ip.To4(); v != nil {\n\t\treturn v, nil\n\t}\n\treturn nil, ErrIEValueNotFound\n}\n\n// MustIPv4 returns IPv4 in net.IP, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIPv4() net.IP {\n\tv, _ := i.IPv4()\n\treturn v\n}\n\n// IPv6 returns IPv6 value in net.IP if the type of IE matches.\nfunc (i *IE) IPv6() (net.IP, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase IPAddress, S103PDNDataForwardingInfo, S1UDataForwarding:\n\t\tip, err := i.IP()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif v := ip.To16(); v != nil {\n\t\t\treturn v, nil\n\t\t}\n\t\treturn nil, ErrIEValueNotFound\n\tcase PDNAddressAllocation:\n\t\tpaa, err := ParsePDNAddressAllocationFields(i.Payload)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif v := paa.IPv6Address.To16(); v != nil {\n\t\t\treturn v, nil\n\t\t}\n\t\treturn nil, ErrIEValueNotFound\n\tcase FullyQualifiedTEID:\n\t\tfteid, err := ParseFullyQualifiedTEIDFields(i.Payload)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif i.HasIPv6() {\n\t\t\tif v := fteid.IPv6Address.To16(); v != nil {\n\t\t\t\treturn v, nil\n\t\t\t}\n\t\t\treturn nil, ErrIEValueNotFound\n\t\t}\n\t\treturn nil, ErrIEValueNotFound\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustIPv6 returns IPv6 in net.IP, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustIPv6() net.IP {\n\tv, _ := i.IPv6()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/ip-addr_test.go",
    "content": "package ie_test\n\nimport (\n\t\"io\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\nfunc TestPDNAddressAllocationIP(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tpaa         *ie.IE\n\t\tpdnType     uint8\n\t\tipv4        net.IP\n\t\tipv6        net.IP\n\t}{\n\t\t{\n\t\t\t\"PDNType IPv4\",\n\t\t\tie.NewPDNAddressAllocation(\"1.2.3.4\"),\n\t\t\tgtpv2.PDNTypeIPv4,\n\t\t\tnet.ParseIP(\"1.2.3.4\"),\n\t\t\tnil,\n\t\t},\n\t\t{\n\t\t\t\"PDNType IPv6\",\n\t\t\tie.NewPDNAddressAllocation(\"::1\"),\n\t\t\tgtpv2.PDNTypeIPv6,\n\t\t\tnil,\n\t\t\tnet.ParseIP(\"::1\"),\n\t\t},\n\t\t{\n\t\t\t\"PDNType IPv4v6\",\n\t\t\tie.NewPDNAddressAllocationDual(\"1.2.3.4\", \"::1\", 64),\n\t\t\tgtpv2.PDNTypeIPv4v6,\n\t\t\tnet.ParseIP(\"1.2.3.4\"),\n\t\t\tnet.ParseIP(\"::1\"),\n\t\t},\n\t\t{\n\t\t\t\"PDNType NonIP\",\n\t\t\tie.NewPDNAddressAllocation(\"\"),\n\t\t\tgtpv2.PDNTypeNonIP,\n\t\t\tnil,\n\t\t\tnil,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.description, func(t *testing.T) {\n\t\t\tpdnType := c.paa.MustPDNType()\n\t\t\tif diff := cmp.Diff(pdnType, c.pdnType); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\n\t\t\tipv4, _ := c.paa.IPv4()\n\t\t\tif diff := cmp.Diff(ipv4, c.ipv4); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\n\t\t\tipv6, _ := c.paa.IPv6()\n\t\t\tif diff := cmp.Diff(ipv6, c.ipv6); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\n\t\t\tip, err := c.paa.IP()\n\t\t\tif err == nil {\n\t\t\t\tv := ipv4\n\t\t\t\tif pdnType == gtpv2.PDNTypeIPv6 {\n\t\t\t\t\tv = ipv6\n\t\t\t\t}\n\t\t\t\tif diff := cmp.Diff(ip, v); diff != \"\" {\n\t\t\t\t\tt.Error(diff)\n\t\t\t\t}\n\t\t\t} else if err != io.ErrUnexpectedEOF {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv2/ie/ldn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewLocalDistinguishedName creates a new LocalDistinguishedName IE.\nfunc NewLocalDistinguishedName(name string) *IE {\n\treturn NewStringIE(LocalDistinguishedName, name)\n}\n\n// LocalDistinguishedName returns LocalDistinguishedName in string if the type of IE matches.\nfunc (i *IE) LocalDistinguishedName() (string, error) {\n\tif i.Type != LocalDistinguishedName {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsString()\n}\n\n// MustLocalDistinguishedName returns LocalDistinguishedName in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustLocalDistinguishedName() string {\n\tv, _ := i.LocalDistinguishedName()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/mbms-flags.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewMBMSFlags creates a new MBMSFlags IE.\nfunc NewMBMSFlags(lmri, msri uint8) *IE {\n\ti := New(MBMSFlags, 0x00, make([]byte, 1))\n\ti.Payload[0] |= (lmri << 1 & 0x02) | (msri & 0x01)\n\treturn i\n}\n\n// MBMSFlags returns MBMSFlags in uint8 if the type of IE matches.\nfunc (i *IE) MBMSFlags() (uint8, error) {\n\tif i.Type != MBMSFlags {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustMBMSFlags returns MBMSFlags in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMBMSFlags() uint8 {\n\tv, _ := i.MBMSFlags()\n\treturn v\n}\n\n// HasMSRI reports whether an IE has MSRI bit.\nfunc (i *IE) HasMSRI() bool {\n\tv, err := i.MBMSFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v)\n}\n\n// HasLMRI reports whether an IE has LMRI bit.\nfunc (i *IE) HasLMRI() bool {\n\tv, err := i.MBMSFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v)\n}\n\n// LocalMBMSBearerContextRelease reports whether the MBMS Session Stop Request\n// message is used to release the MBMS Bearer Context locally in the MME/SGSN.\nfunc (i *IE) LocalMBMSBearerContextRelease() bool {\n\tv, err := i.MBMSFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn v&0x02 == 1\n}\n\n// MBMSSessionReEstablishment reports whether the MBMS Session Start Request\n// message is used to re-establish an MBMS session.\nfunc (i *IE) MBMSSessionReEstablishment() bool {\n\tv, err := i.MBMSFlags()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn v&0x01 == 1\n}\n"
  },
  {
    "path": "gtpv2/ie/mcc-mnc.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"errors\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// MCC returns MCC in string if the type of IE matches.\nfunc (i *IE) MCC() (string, error) {\n\tif len(i.Payload) < 3 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase ServingNetwork, PLMNID:\n\t\tmcc, _, err := utils.DecodePLMN(i.Payload)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn mcc, nil\n\tcase GlobalCNID, TraceReference, GUTI, UserCSGInformation:\n\t\tmcc, _, err := utils.DecodePLMN(i.Payload[:3])\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn mcc, nil\n\tcase UserLocationInformation:\n\t\tuliFields, err := i.UserLocationInformation()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tswitch {\n\t\tcase uliFields.HasCGI():\n\t\t\treturn uliFields.CGI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasSAI():\n\t\t\treturn uliFields.SAI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasRAI():\n\t\t\treturn uliFields.RAI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasTAI():\n\t\t\treturn uliFields.TAI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasECGI():\n\t\t\treturn uliFields.ECGI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasLAI():\n\t\t\treturn uliFields.LAI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasMENBI():\n\t\t\treturn uliFields.MENBI.MCCFromPLMN(), nil\n\t\tcase uliFields.HasEMENBI():\n\t\t\treturn uliFields.EMENBI.MCCFromPLMN(), nil\n\t\t}\n\t\treturn \"\", errors.New(\"MCC is not present in ULI\")\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMCC returns MCC in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMCC() string {\n\tv, _ := i.MCC()\n\treturn v\n}\n\n// MNC returns MNC in string if the type of IE matches.\nfunc (i *IE) MNC() (string, error) {\n\tif len(i.Payload) < 3 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase ServingNetwork, PLMNID:\n\t\t_, mnc, err := utils.DecodePLMN(i.Payload)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn mnc, nil\n\tcase GlobalCNID, TraceReference, GUTI, UserCSGInformation:\n\t\t_, mnc, err := utils.DecodePLMN(i.Payload[:3])\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn mnc, nil\n\tcase UserLocationInformation:\n\t\tuliFields, err := i.UserLocationInformation()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tswitch {\n\t\tcase uliFields.HasCGI():\n\t\t\treturn uliFields.CGI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasSAI():\n\t\t\treturn uliFields.SAI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasRAI():\n\t\t\treturn uliFields.RAI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasTAI():\n\t\t\treturn uliFields.TAI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasECGI():\n\t\t\treturn uliFields.ECGI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasLAI():\n\t\t\treturn uliFields.LAI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasMENBI():\n\t\t\treturn uliFields.MENBI.MNCFromPLMN(), nil\n\t\tcase uliFields.HasEMENBI():\n\t\t\treturn uliFields.EMENBI.MNCFromPLMN(), nil\n\t\t}\n\t\treturn \"\", errors.New(\"MNC is not present in ULI\")\n\tdefault:\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustMNC returns MNC in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMNC() string {\n\tv, _ := i.MNC()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/mcc-mnc_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"testing\"\n)\n\nfunc TestMCCAndMNCFromULI(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\ti       *IE\n\t\twantMCC string\n\t\twantMNC string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from CGI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tNewCGI(\"123\", \"45\", 0x1111, 0x2222), nil, nil, nil, nil, nil, nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"123\",\n\t\t\twantMNC: \"45\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from SAI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, NewSAI(\"234\", \"56\", 0x1111, 0x3333), nil, nil, nil, nil, nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"234\",\n\t\t\twantMNC: \"56\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from RAI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, NewRAI(\"456\", \"78\", 0x1111, 0x4444), nil, nil, nil, nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"456\",\n\t\t\twantMNC: \"78\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from TAI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, nil, NewTAI(\"567\", \"89\", 0x5555), nil, nil, nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"567\",\n\t\t\twantMNC: \"89\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from ECGI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, nil, nil, NewECGI(\"678\", \"90\", 0x66666666), nil, nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"678\",\n\t\t\twantMNC: \"90\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from LAI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, nil, nil, nil, NewLAI(\"789\", \"01\", 0x1111), nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"789\",\n\t\t\twantMNC: \"01\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from MENBI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, nil, nil, nil, nil, NewMENBI(\"890\", \"12\", 0x11111111), nil,\n\t\t\t),\n\t\t\twantMCC: \"890\",\n\t\t\twantMNC: \"12\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from EMENBI\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, nil, nil, nil, nil, nil, NewEMENBI(\"321\", \"54\", 0x22222222),\n\t\t\t),\n\t\t\twantMCC: \"321\",\n\t\t\twantMNC: \"54\",\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting empty strings when uli does not contain information elemtents\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tnil, nil, nil, nil, nil, nil, nil, nil,\n\t\t\t),\n\t\t\twantMCC: \"\",\n\t\t\twantMNC: \"\",\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"Test getting MCC and MNC from ULI from CGI when all elements are given\",\n\t\t\ti: NewUserLocationInformationStruct(\n\t\t\t\tNewCGI(\"123\", \"45\", 0x1111, 0x2222),\n\t\t\t\tNewSAI(\"234\", \"56\", 0x1111, 0x3333),\n\t\t\t\tNewRAI(\"456\", \"78\", 0x1111, 0x4444),\n\t\t\t\tNewTAI(\"567\", \"89\", 0x5555),\n\t\t\t\tNewECGI(\"678\", \"90\", 0x66666666),\n\t\t\t\tNewLAI(\"789\", \"01\", 0x1111),\n\t\t\t\tNewMENBI(\"890\", \"12\", 0x11111111),\n\t\t\t\tNewEMENBI(\"321\", \"54\", 0x22222222),\n\t\t\t),\n\t\t\twantMCC: \"123\",\n\t\t\twantMNC: \"45\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := tt.i.MCC()\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"IE.MCC() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got != tt.wantMCC {\n\t\t\t\tt.Errorf(\"IE.MCC() = %v, want %v\", got, tt.wantMCC)\n\t\t\t}\n\t\t\tgot, err = tt.i.MNC()\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"IE.MNC() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif got != tt.wantMNC {\n\t\t\t\tt.Errorf(\"IE.MNC() = %v, want %v\", got, tt.wantMNC)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv2/ie/mei.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewMobileEquipmentIdentity creates a new MobileEquipmentIdentity IE.\nfunc NewMobileEquipmentIdentity(mei string) *IE {\n\tm, err := utils.StrToSwappedBytes(mei, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn New(MobileEquipmentIdentity, 0x00, m)\n}\n\n// MobileEquipmentIdentity returns MobileEquipmentIdentity in string if the\n// type of IE matches.\nfunc (i *IE) MobileEquipmentIdentity() (string, error) {\n\tif i.Type != MobileEquipmentIdentity {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tstr := utils.SwappedBytesToStr(i.Payload, false)\n\treturn strings.TrimSuffix(str, \"f\"), nil\n}\n\n// MustMobileEquipmentIdentity returns MobileEquipmentIdentity in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMobileEquipmentIdentity() string {\n\tv, _ := i.MobileEquipmentIdentity()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/msisdn.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewMSISDN creates a new MSISDN IE.\nfunc NewMSISDN(msisdn string) *IE {\n\tm, err := utils.StrToSwappedBytes(msisdn, \"f\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn New(MSISDN, 0x00, m)\n}\n\n// MSISDN returns MSISDN in string if the type of IE matches.\nfunc (i *IE) MSISDN() (string, error) {\n\tif i.Type != MSISDN {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tstr := utils.SwappedBytesToStr(i.Payload, false)\n\treturn strings.TrimSuffix(str, \"f\"), nil\n}\n\n// MustMSISDN returns MSISDN in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustMSISDN() string {\n\tv, _ := i.MSISDN()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/node-features.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewNodeFeatures creates a new NodeFeatures IE.\nfunc NewNodeFeatures(flags uint8) *IE {\n\treturn NewUint8IE(NodeFeatures, flags)\n}\n\n// NodeFeatures returns NodeFeatures in uint8 if the type of IE matches.\nfunc (i *IE) NodeFeatures() (uint8, error) {\n\tif i.Type != NodeFeatures {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustNodeFeatures returns NodeFeatures in uint8 if the type of IE matches.\nfunc (i *IE) MustNodeFeatures() uint8 {\n\tv, _ := i.NodeFeatures()\n\treturn v\n}\n\n// HasPRN reports whether an IE has PRN bit.\nfunc (i *IE) HasPRN() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has1stBit(v)\n}\n\n// HasMABR reports whether an IE has MABR bit.\nfunc (i *IE) HasMABR() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has2ndBit(v)\n}\n\n// HasNTSR reports whether an IE has NTSR bit.\nfunc (i *IE) HasNTSR() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has3rdBit(v)\n}\n\n// HasCIOT reports whether an IE has CIOT bit.\nfunc (i *IE) HasCIOT() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has4thBit(v)\n}\n\n// HasS1UN reports whether an IE has S1UN bit.\nfunc (i *IE) HasS1UN() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has5thBit(v)\n}\n\n// HasETH reports whether an IE has ETH bit.\nfunc (i *IE) HasETH() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has6thBit(v)\n}\n\n// HasMTEDT reports whether an IE has MTEDT bit.\nfunc (i *IE) HasMTEDT() bool {\n\tv, err := i.NodeFeatures()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn has7thBit(v)\n}\n"
  },
  {
    "path": "gtpv2/ie/node-type.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewNodeType creates a new NodeType IE.\nfunc NewNodeType(nodeType uint8) *IE {\n\treturn NewUint8IE(NodeType, nodeType)\n}\n\n// NodeType returns NodeType in uint8 if the type of IE matches.\nfunc (i *IE) NodeType() (uint8, error) {\n\tif i.Type != NodeType {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustNodeType returns NodeType in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustNodeType() uint8 {\n\tv, _ := i.NodeType()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/p-tmsi-signature.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewPTMSISignature creates a new PTMSISignature IE.\nfunc NewPTMSISignature(sig uint32) *IE {\n\treturn New(PTMSISignature, 0x00, utils.Uint32To24(sig))\n}\n\n// PTMSISignature returns PTMSISignature value in uint32 if type matches.\nfunc (i *IE) PTMSISignature() (uint32, error) {\n\tif i.Type != PTMSISignature {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.Uint24To32(i.Payload), nil\n}\n\n// MustPTMSISignature returns PTMSISignature in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPTMSISignature() uint32 {\n\tv, _ := i.PTMSISignature()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/p-tmsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewPacketTMSI creates a new PacketTMSI IE.\nfunc NewPacketTMSI(ptmsi uint32) *IE {\n\treturn NewUint32IE(PacketTMSI, ptmsi)\n}\n\n// PacketTMSI returns PacketTMSI value in uint32 if type matches.\nfunc (i *IE) PacketTMSI() (uint32, error) {\n\tif i.Type != PacketTMSI {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint32()\n}\n\n// MustPacketTMSI returns PacketTMSI in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPacketTMSI() uint32 {\n\tv, _ := i.PacketTMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/paa.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"net\"\n)\n\n// PDN Type definitions.\nconst (\n\t_ uint8 = iota\n\tpdnTypeIPv4\n\tpdnTypeIPv6\n\tpdnTypeIPv4v6\n\tpdnTypeNonIP\n)\n\n// NewPDNAddressAllocation creates a new PDNAddressAllocation IE.\n//\n// The PDN Type field is automatically judged by the format of given addr,\n// If it cannot be converted as neither IPv4 nor IPv6, PDN Type will be Non-IP.\n//\n// NOTE: IPv6 Prefix Length will be set to 0 when an IPv6 address is given to this.\n// Use NewPDNAddressAllocationIPv6 instead to set the correct value.\nfunc NewPDNAddressAllocation(addr string) *IE {\n\treturn NewPDNAddressAllocationNetIP(net.ParseIP(addr), 0)\n}\n\n// NewPDNAddressAllocation creates a new PDNAddressAllocation IE with IPv6 value.\nfunc NewPDNAddressAllocationIPv6(addr string, prefix uint8) *IE {\n\treturn NewPDNAddressAllocationNetIP(net.ParseIP(addr), prefix)\n}\n\n// NewPDNAddressAllocationDual creates a new PDNAddressAllocation IE with\n// IPv4 address and IPv6 address given.\n//\n// If they cannot be converted as IPv4/IPv6, PDN Type will be Non-IP.\nfunc NewPDNAddressAllocationDual(v4addr, v6addr string, v6prefix uint8) *IE {\n\treturn NewPDNAddressAllocationDualNetIP(net.ParseIP(v4addr), net.ParseIP(v6addr), v6prefix)\n}\n\n// NewPDNAddressAllocationNetIP creates a new PDNAddressAllocation IE from net.IP.\nfunc NewPDNAddressAllocationNetIP(ip net.IP, v6prefix uint8) *IE {\n\tvar v *PDNAddressAllocationFields\n\tif v4 := ip.To4(); v4 != nil {\n\t\tv = NewPDNAddressAllocationFields(pdnTypeIPv4, v4, nil, 0)\n\t} else if v6 := ip.To16(); v6 != nil {\n\t\tv = NewPDNAddressAllocationFields(pdnTypeIPv6, nil, v6, v6prefix)\n\t} else {\n\t\tv = NewPDNAddressAllocationFields(pdnTypeNonIP, nil, nil, 0)\n\t}\n\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(PDNAddressAllocation, 0x00, b)\n}\n\n// NewPDNAddressAllocationDualNetIP creates a new PDNAddressAllocation IE from\n// IPv4 and IPv6 in net.IP.\nfunc NewPDNAddressAllocationDualNetIP(v4, v6 net.IP, v6prefix uint8) *IE {\n\tv := NewPDNAddressAllocationFields(pdnTypeIPv4v6, v4, v6, v6prefix)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(PDNAddressAllocation, 0x00, b)\n}\n\n// PDNAddressAllocationFields is a set of fields in PDNAddressAllocation IE.\ntype PDNAddressAllocationFields struct {\n\tPDNType          uint8 // 3-bit\n\tIPv4Address      net.IP\n\tIPv6PrefixLength uint8\n\tIPv6Address      net.IP\n}\n\n// NewPDNAddressAllocationFields creates a new PDNAddressAllocationFields.\nfunc NewPDNAddressAllocationFields(pType uint8, v4, v6 net.IP, prefix uint8) *PDNAddressAllocationFields {\n\treturn &PDNAddressAllocationFields{\n\t\tPDNType:          pType,\n\t\tIPv4Address:      v4,\n\t\tIPv6PrefixLength: prefix,\n\t\tIPv6Address:      v6,\n\t}\n}\n\n// Marshal serializes PDNAddressAllocationFields.\nfunc (f *PDNAddressAllocationFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes PDNAddressAllocationFields.\nfunc (f *PDNAddressAllocationFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.PDNType & 0x07\n\toffset := 1\n\n\tswitch f.PDNType {\n\tcase pdnTypeIPv4:\n\t\tif l < offset+4 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tif f.IPv4Address != nil {\n\t\t\tcopy(b[offset:offset+4], f.IPv4Address.To4())\n\t\t}\n\n\t\treturn nil\n\tcase pdnTypeIPv6:\n\t\tif l < offset+17 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tb[offset] = f.IPv6PrefixLength\n\t\tcopy(b[offset+1:offset+17], f.IPv6Address.To16())\n\n\t\treturn nil\n\tcase pdnTypeIPv4v6:\n\t\tif l < offset+21 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tb[offset] = f.IPv6PrefixLength\n\t\tcopy(b[offset+1:offset+17], f.IPv6Address.To16())\n\t\tcopy(b[offset+17:offset+21], f.IPv4Address.To4())\n\n\t\treturn nil\n\tcase pdnTypeNonIP: // no payload\n\t\treturn nil\n\tdefault:\n\t\treturn nil\n\t}\n\n}\n\n// ParsePDNAddressAllocationFields decodes PDNAddressAllocationFields.\nfunc ParsePDNAddressAllocationFields(b []byte) (*PDNAddressAllocationFields, error) {\n\tf := &PDNAddressAllocationFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into PDNAddressAllocationFields.\nfunc (f *PDNAddressAllocationFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.PDNType = b[0] & 0x07\n\toffset := 1\n\n\tswitch f.PDNType {\n\tcase pdnTypeIPv4:\n\t\tif l < offset+4 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.IPv4Address = b[offset : offset+4]\n\n\t\treturn nil\n\tcase pdnTypeIPv6:\n\t\tif l < offset+17 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.IPv6PrefixLength = b[offset]\n\t\tf.IPv6Address = b[offset+1 : offset+17]\n\n\t\treturn nil\n\tcase pdnTypeIPv4v6:\n\t\tif l < offset+21 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.IPv6PrefixLength = b[offset]\n\t\tf.IPv6Address = b[offset+1 : offset+17]\n\t\tf.IPv4Address = b[offset+17 : offset+21]\n\n\t\treturn nil\n\tcase pdnTypeNonIP: // no payload\n\t\treturn nil\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// MarshalLen returns the serial length of PDNAddressAllocationFields in int.\nfunc (f *PDNAddressAllocationFields) MarshalLen() int {\n\tl := 1\n\tswitch f.PDNType {\n\tcase pdnTypeIPv4:\n\t\tl += 4\n\tcase pdnTypeIPv6:\n\t\tl += 17\n\tcase pdnTypeIPv4v6:\n\t\tl += 21\n\tcase pdnTypeNonIP:\n\t\t// no payload, do nothing\n\t}\n\n\treturn l\n}\n"
  },
  {
    "path": "gtpv2/ie/paging-and-service-information.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n)\n\n// NewPagingAndServiceInformation creates a new PagingAndServiceInformation IE.\nfunc NewPagingAndServiceInformation(ebi, flags, ppi uint8) *IE {\n\tv := NewPagingAndServiceInformationFields(ebi, flags, ppi)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(PagingAndServiceInformation, 0x00, b)\n}\n\n// PagingAndServiceInformation returns PagingAndServiceInformation in PagingAndServiceInformationFields type if the type of IE matches.\nfunc (i *IE) PagingAndServiceInformation() (*PagingAndServiceInformationFields, error) {\n\tswitch i.Type {\n\tcase PagingAndServiceInformation:\n\t\treturn ParsePagingAndServiceInformationFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// PagingAndServiceInformationFields is a set of fields in PagingAndServiceInformation IE.\ntype PagingAndServiceInformationFields struct {\n\tEPSBearerID            uint8 // 4-bit\n\tFlags                  uint8 // 1st bit\n\tPagingPolicyIndication uint8 // 7-bit\n}\n\n// NewPagingAndServiceInformationFields creates a new PagingAndServiceInformationFields.\nfunc NewPagingAndServiceInformationFields(ebi, flags, ppi uint8) *PagingAndServiceInformationFields {\n\treturn &PagingAndServiceInformationFields{\n\t\tEPSBearerID:            ebi & 0x0f,\n\t\tFlags:                  flags, // no mask, may be used in the future\n\t\tPagingPolicyIndication: ppi & 0x7f,\n\t}\n}\n\n// Marshal serializes PagingAndServiceInformationFields.\nfunc (f *PagingAndServiceInformationFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes PagingAndServiceInformationFields.\nfunc (f *PagingAndServiceInformationFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.EPSBearerID & 0x0f\n\tb[1] = f.Flags\n\tif has1stBit(f.Flags) {\n\t\tif l < 3 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tb[2] = f.PagingPolicyIndication & 0x7f\n\t}\n\n\treturn nil\n}\n\n// ParsePagingAndServiceInformationFields decodes PagingAndServiceInformationFields.\nfunc ParsePagingAndServiceInformationFields(b []byte) (*PagingAndServiceInformationFields, error) {\n\tf := &PagingAndServiceInformationFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into PagingAndServiceInformationFields.\nfunc (f *PagingAndServiceInformationFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.EPSBearerID = b[0] & 0x0f\n\tf.Flags = b[0]\n\tif has1stBit(f.Flags) {\n\t\tif l < 3 {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\t\tf.PagingPolicyIndication = b[2] & 0x7f\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of PagingAndServiceInformationFields in int.\nfunc (f *PagingAndServiceInformationFields) MarshalLen() int {\n\tl := 2\n\tif has1stBit(f.Flags) {\n\t\tl++\n\t}\n\treturn l\n}\n\n// PagingPolicyIndication returns PagingPolicyIndication in uint8 if the type of IE matches.\nfunc (i *IE) PagingPolicyIndication() (uint8, error) {\n\tswitch i.Type {\n\tcase PagingAndServiceInformation:\n\t\tf, err := ParsePagingAndServiceInformationFields(i.Payload)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\tif !has1stBit(f.Flags) {\n\t\t\treturn 0, ErrIEValueNotFound\n\t\t}\n\n\t\treturn f.PagingPolicyIndication, nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustPagingPolicyIndication returns PagingPolicyIndication in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPagingPolicyIndication() uint8 {\n\tv, _ := i.PagingPolicyIndication()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/pco-ppp.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"net\"\n)\n\nconst (\n\tPCOPPPConfigurationRequest = 0x01\n\tPCOPPPConfigurationAck     = 0x02\n)\n\n// PCOPPP represents a PPP header and its contents used in PCO.\n//\n// TODO: create another package with full implementation.\ntype PCOPPP struct {\n\tCode       uint8\n\tIdentifier uint8\n\tLength     uint16\n\tPayload    []byte\n}\n\n// NewPCOPPP creates a new PCOPPP.\nfunc NewPCOPPP(code, id uint8, payload []byte) *PCOPPP {\n\treturn &PCOPPP{\n\t\tCode:       code,\n\t\tIdentifier: id,\n\t\tLength:     uint16(4 + len(payload)),\n\t\tPayload:    payload,\n\t}\n}\n\n// NewPCOPPPWithPAP creates a new PCOPPP with given PAP.\nfunc NewPCOPPPWithPAP(code, id uint8, peer, pass string) *PCOPPP {\n\tpap, err := NewPAPFields(peer, pass).Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn NewPCOPPP(code, id, pap)\n}\n\n// NewPCOPPPWithCHAP creates a new PCOPPP with given CHAP.\nfunc NewPCOPPPWithCHAP(code, id uint8, val []byte, pass string) *PCOPPP {\n\tpap, err := NewCHAPFields(val, pass).Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn NewPCOPPP(code, id, pap)\n}\n\n// NewPCOPPPWithIPCPOptions creates a new PCOPPP with given IPCPOptions.\nfunc NewPCOPPPWithIPCPOptions(code, id uint8, opts ...*IPCPOption) *PCOPPP {\n\toffset := 0\n\tb := make([]byte, offset)\n\tfor _, o := range opts {\n\t\tl := o.MarshalLen()\n\t\tb = append(b, make([]byte, l)...)\n\t\tif err := o.MarshalTo(b[offset : offset+l]); err != nil {\n\t\t\treturn nil\n\t\t}\n\n\t\toffset += l\n\t}\n\n\treturn NewPCOPPP(code, id, b)\n}\n\n// Marshal serializes PCOPPP.\nfunc (p *PCOPPP) Marshal() ([]byte, error) {\n\tb := make([]byte, p.MarshalLen())\n\tif err := p.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes PCOPPP.\nfunc (p *PCOPPP) MarshalTo(b []byte) error {\n\tif len(b) < 5 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tb[0] = p.Code\n\tb[1] = p.Identifier\n\tbinary.BigEndian.PutUint16(b[2:4], p.Length)\n\n\tcopy(b[4:], p.Payload)\n\n\treturn nil\n}\n\n// ParsePCOPPP decodes PCOPPP.\nfunc ParsePCOPPP(b []byte) (*PCOPPP, error) {\n\tp := &PCOPPP{}\n\tif err := p.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn p, nil\n}\n\n// UnmarshalBinary decodes given bytes into PCOPPP.\nfunc (p *PCOPPP) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 5 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\tp.Code = b[0]\n\tp.Identifier = b[1]\n\tp.Length = binary.BigEndian.Uint16(b[2:4])\n\n\tif l < int(p.Length) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tp.Payload = b[4:int(p.Length)]\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of PCOPPP in int.\nfunc (p *PCOPPP) MarshalLen() int {\n\treturn 4 + len(p.Payload)\n}\n\n// PAPFields represents a PAP payload on PPP protocol.\n//\n// TODO: create another package with full implementation.\ntype PAPFields struct {\n\tPeerIDLength   uint8\n\tPeerID         string\n\tPasswordLength uint8\n\tPassword       string\n}\n\n// NewPAPFields creates a new PAPFields.\nfunc NewPAPFields(id, pass string) *PAPFields {\n\treturn &PAPFields{\n\t\tPeerIDLength:   uint8(len([]byte(id))),\n\t\tPeerID:         id,\n\t\tPasswordLength: uint8(len([]byte(pass))),\n\t\tPassword:       pass,\n\t}\n}\n\n// Marshal serializes PAPFields.\nfunc (p *PAPFields) Marshal() ([]byte, error) {\n\tb := make([]byte, p.MarshalLen())\n\tif err := p.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes PAPFields.\nfunc (p *PAPFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tb[0] = p.PeerIDLength\n\toffset := 1\n\n\tif l < offset+int(p.PeerIDLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+int(p.PeerIDLength)], p.PeerID)\n\toffset += int(p.PeerIDLength)\n\n\tb[offset] = p.PasswordLength\n\toffset++\n\n\tif l < offset+int(p.PasswordLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+int(p.PasswordLength)], p.Password)\n\n\treturn nil\n}\n\n// ParsePAPFields decodes PAPFields.\nfunc ParsePAPFields(b []byte) (*PAPFields, error) {\n\tp := &PAPFields{}\n\tif err := p.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn p, nil\n}\n\n// UnmarshalBinary decodes given bytes into PAPFields.\nfunc (p *PAPFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\tp.PeerIDLength = b[0]\n\toffset := 1\n\n\tif l < offset+int(p.PeerIDLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tp.PeerID = string(b[offset : offset+int(p.PeerIDLength)])\n\toffset += int(p.PeerIDLength)\n\n\tp.PasswordLength = b[offset]\n\toffset++\n\n\tif l < offset+int(p.PasswordLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tp.Password = string(b[offset : offset+int(p.PasswordLength)])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of PAPFields in int.\nfunc (p *PAPFields) MarshalLen() int {\n\treturn 2 + len([]byte(p.PeerID)) + len([]byte(p.Password))\n}\n\n// CHAPFields represents a PAP payload on PPP protocol.\n//\n// TODO: create another package with full implementation.\ntype CHAPFields struct {\n\tValueSize uint8\n\tValue     []byte\n\tName      string\n}\n\n// NewCHAPFields creates a new CHAPFields.\nfunc NewCHAPFields(val []byte, name string) *CHAPFields {\n\treturn &CHAPFields{\n\t\tValueSize: uint8(len(val)),\n\t\tValue:     val,\n\t\tName:      name,\n\t}\n}\n\n// Marshal serializes CHAPFields.\nfunc (c *CHAPFields) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes CHAPFields.\nfunc (c *CHAPFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tb[0] = c.ValueSize\n\toffset := 1\n\n\tif l < offset+int(c.ValueSize) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+int(c.ValueSize)], c.Value)\n\toffset += int(c.ValueSize)\n\n\tcopy(b[offset:], c.Name)\n\n\treturn nil\n}\n\n// ParseCHAPFields decodes CHAPFields.\nfunc ParseCHAPFields(b []byte) (*CHAPFields, error) {\n\tc := &CHAPFields{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes into CHAPFields.\nfunc (c *CHAPFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\tc.ValueSize = b[0]\n\toffset := 1\n\n\tif l < offset+int(c.ValueSize) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tc.Value = b[offset : offset+int(c.ValueSize)]\n\toffset += int(c.ValueSize)\n\n\tc.Name = string(b[offset:])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of CHAPFields in int.\nfunc (c *CHAPFields) MarshalLen() int {\n\treturn 1 + len(c.Value) + len([]byte(c.Name))\n}\n\n// IPCP Options.\n//\n// TODO: perhaps there are more options but...\nconst (\n\tIPCPOptionIPAddress    uint8 = 3\n\tIPCPOptionMobileIPv4   uint8 = 4\n\tIPCPOptionPrimaryDNS   uint8 = 129\n\tIPCPOptionSecondaryDNS uint8 = 131\n)\n\n// IPCPOption is a IPCP Option.\ntype IPCPOption struct {\n\tType    uint8\n\tLength  uint8\n\tPayload []byte\n}\n\n// NewIPCPOption creates an IPCPOption with given IP address.\nfunc NewIPCPOption(typ uint8, payload []byte) *IPCPOption {\n\treturn &IPCPOption{\n\t\tType:    typ,\n\t\tLength:  uint8(2 + len(payload)),\n\t\tPayload: payload,\n\t}\n}\n\n// NewIPCPOptionIPAddress creates an IPCPOption with given IP address.\nfunc NewIPCPOptionIPAddress(ip net.IP) *IPCPOption {\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn NewIPCPOption(IPCPOptionIPAddress, v4)\n\t}\n\n\t// IPv6\n\treturn NewIPCPOption(IPCPOptionIPAddress, ip)\n}\n\n// NewIPCPOptionMobileIPv4 creates an IPCPOption with given IP address.\nfunc NewIPCPOptionMobileIPv4(ip net.IP) *IPCPOption {\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn NewIPCPOption(IPCPOptionMobileIPv4, v4)\n\t}\n\n\t// IPv6\n\treturn NewIPCPOption(IPCPOptionMobileIPv4, ip)\n}\n\n// NewIPCPOptionPrimaryDNS creates an IPCPOption with given IP address.\nfunc NewIPCPOptionPrimaryDNS(ip net.IP) *IPCPOption {\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn NewIPCPOption(IPCPOptionPrimaryDNS, v4)\n\t}\n\n\t// IPv6\n\treturn NewIPCPOption(IPCPOptionPrimaryDNS, ip)\n}\n\n// NewIPCPOptionSecondaryDNS creates an IPCPOption with given IP address.\nfunc NewIPCPOptionSecondaryDNS(ip net.IP) *IPCPOption {\n\tv4 := ip.To4()\n\n\t// IPv4\n\tif v4 != nil {\n\t\treturn NewIPCPOption(IPCPOptionSecondaryDNS, v4)\n\t}\n\n\t// IPv6\n\treturn NewIPCPOption(IPCPOptionSecondaryDNS, ip)\n}\n\n// Marshal serializes IPCPOption.\nfunc (o *IPCPOption) Marshal() ([]byte, error) {\n\tb := make([]byte, o.MarshalLen())\n\tif err := o.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes IPCPOption.\nfunc (o *IPCPOption) MarshalTo(b []byte) error {\n\tif len(b) < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tb[0] = o.Type\n\tb[1] = o.Length\n\n\tcopy(b[2:], o.Payload)\n\n\treturn nil\n}\n\n// ParseIPCPOption decodes IPCPOption.\nfunc ParseIPCPOption(b []byte) (*IPCPOption, error) {\n\to := &IPCPOption{}\n\tif err := o.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn o, nil\n}\n\n// UnmarshalBinary decodes given bytes into IPCPOption.\nfunc (o *IPCPOption) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\to.Type = b[0]\n\to.Length = b[1]\n\n\tif l < int(o.Length) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\to.Payload = b[2:int(o.Length)]\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of IPCPOption in int.\nfunc (o *IPCPOption) MarshalLen() int {\n\treturn 2 + len(o.Payload)\n}\n"
  },
  {
    "path": "gtpv2/ie/pco-ppp_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie_test\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\nvar (\n\tip1 = net.ParseIP(\"1.1.1.1\")\n\tip2 = net.ParseIP(\"2.2.2.2\")\n)\n\nfunc TestPCOPPP(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  *ie.PCOPPP\n\t\tserialized  []byte\n\t}{\n\t\t{\n\t\t\t\"PAP\",\n\t\t\tie.NewPCOPPPWithPAP(ie.PCOPPPConfigurationRequest, 0, \"foo\", \"bar\"),\n\t\t\t[]byte{0x01, 0x00, 0x00, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x03, 0x62, 0x61, 0x72},\n\t\t}, {\n\t\t\t\"CHAP\",\n\t\t\tie.NewPCOPPPWithCHAP(ie.PCOPPPConfigurationRequest, 0, []byte{0xde, 0xad, 0xbe, 0xef}, \"foo\"),\n\t\t\t[]byte{0x01, 0x00, 0x00, 0x0c, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x66, 0x6f, 0x6f},\n\t\t}, {\n\t\t\t\"IPCPOptions/IPAddress+PrimaryDNS\",\n\t\t\tie.NewPCOPPPWithIPCPOptions(\n\t\t\t\tie.PCOPPPConfigurationRequest,\n\t\t\t\t0,\n\t\t\t\tie.NewIPCPOptionIPAddress(ip1),\n\t\t\t\tie.NewIPCPOptionPrimaryDNS(ip2),\n\t\t\t),\n\t\t\t[]byte{0x01, 0x00, 0x00, 0x10, 0x03, 0x06, 0x01, 0x01, 0x01, 0x01, 0x81, 0x06, 0x02, 0x02, 0x02, 0x02},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"serialize/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"decode/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.ParsePCOPPP(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\topt := cmp.AllowUnexported(*got, *c.structured)\n\t\t\tif diff := cmp.Diff(got, c.structured, opt); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestPCOPPPPAPFields(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  *ie.PAPFields\n\t\tserialized  []byte\n\t}{\n\t\t{\n\t\t\t\"Normal\",\n\t\t\tie.NewPAPFields(\"foo\", \"bar\"),\n\t\t\t[]byte{0x03, 0x66, 0x6f, 0x6f, 0x03, 0x62, 0x61, 0x72},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"serialize/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"decode/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.ParsePAPFields(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\topt := cmp.AllowUnexported(*got, *c.structured)\n\t\t\tif diff := cmp.Diff(got, c.structured, opt); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestPCOPPPCHAPFields(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  *ie.CHAPFields\n\t\tserialized  []byte\n\t}{\n\t\t{\n\t\t\t\"Normal\",\n\t\t\tie.NewCHAPFields([]byte{0xde, 0xad, 0xbe, 0xef}, \"foo\"),\n\t\t\t[]byte{0x04, 0xde, 0xad, 0xbe, 0xef, 0x66, 0x6f, 0x6f},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"serialize/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"decode/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.ParseCHAPFields(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\topt := cmp.AllowUnexported(*got, *c.structured)\n\t\t\tif diff := cmp.Diff(got, c.structured, opt); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestPCOPPPIPCPOption(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstructured  *ie.IPCPOption\n\t\tserialized  []byte\n\t}{\n\t\t{\n\t\t\t\"IPAddress\",\n\t\t\tie.NewIPCPOptionIPAddress(ip1),\n\t\t\t[]byte{0x03, 0x06, 0x01, 0x01, 0x01, 0x01},\n\t\t}, {\n\t\t\t\"PrimaryDNS\",\n\t\t\tie.NewIPCPOptionPrimaryDNS(ip2),\n\t\t\t[]byte{0x81, 0x06, 0x02, 0x02, 0x02, 0x02},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"serialize/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := c.structured.Marshal()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(got, c.serialized); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"decode/\"+c.description, func(t *testing.T) {\n\t\t\tgot, err := ie.ParseIPCPOption(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\topt := cmp.AllowUnexported(*got, *c.structured)\n\t\t\tif diff := cmp.Diff(got, c.structured, opt); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv2/ie/pco.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n)\n\n// ConfigurationProtocol definitions.\nconst (\n\tConfigurationProtocolPPPForUseWithIPPDPTypeOrIPPDNType uint8 = 0b000\n)\n\n// NewProtocolConfigurationOptions creates a new ProtocolConfigurationOptions IE.\nfunc NewProtocolConfigurationOptions(proto uint8, options ...*PCOContainer) *IE {\n\tv := NewProtocolConfigurationOptionsFields(proto, options...)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(ProtocolConfigurationOptions, 0x00, b)\n}\n\n// ProtocolConfigurationOptions returns ProtocolConfigurationOptions in\n// ProtocolConfigurationOptionsFields type if the type of IE matches.\nfunc (i *IE) ProtocolConfigurationOptions() (*ProtocolConfigurationOptionsFields, error) {\n\tswitch i.Type {\n\tcase ProtocolConfigurationOptions:\n\t\tif len(i.Payload) < 1 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\n\t\treturn ParseProtocolConfigurationOptionsFields(i.Payload)\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to retrieve ProtocolConfigurationOptions: %w\", err)\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == ProtocolConfigurationOptions {\n\t\t\t\treturn child.ProtocolConfigurationOptions()\n\t\t\t}\n\t\t}\n\t\treturn nil, ErrIENotFound\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustProtocolConfigurationOptions returns ProtocolConfigurationOptions in *ProtocolConfigurationOptionsFields, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustProtocolConfigurationOptions() *ProtocolConfigurationOptionsFields {\n\tv, _ := i.ProtocolConfigurationOptions()\n\treturn v\n}\n\n// ProtocolConfigurationOptionsFields is a set of fields in ProtocolConfigurationOptions IE.\ntype ProtocolConfigurationOptionsFields struct {\n\tExtension             uint8 // bit 8 of octet 1\n\tConfigurationProtocol uint8 // bit 1-3 of octet 1\n\tProtocolOrContainers  []*PCOContainer\n}\n\n// NewProtocolConfigurationOptionsFields creates a new ProtocolConfigurationOptionsFields.\nfunc NewProtocolConfigurationOptionsFields(proto uint8, opts ...*PCOContainer) *ProtocolConfigurationOptionsFields {\n\tf := &ProtocolConfigurationOptionsFields{ConfigurationProtocol: proto}\n\tf.ProtocolOrContainers = append(f.ProtocolOrContainers, opts...)\n\n\treturn f\n}\n\n// Marshal serializes ProtocolConfigurationOptionsFields.\nfunc (f *ProtocolConfigurationOptionsFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes ProtocolConfigurationOptionsFields.\nfunc (f *ProtocolConfigurationOptionsFields) MarshalTo(b []byte) error {\n\tb[0] = (f.ConfigurationProtocol & 0x07) | 0x80\n\toffset := 1\n\tfor _, opt := range f.ProtocolOrContainers {\n\t\tif err := opt.MarshalTo(b[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += opt.MarshalLen()\n\t}\n\n\treturn nil\n}\n\n// ParseProtocolConfigurationOptionsFields decodes ProtocolConfigurationOptionsFields.\nfunc ParseProtocolConfigurationOptionsFields(b []byte) (*ProtocolConfigurationOptionsFields, error) {\n\tf := &ProtocolConfigurationOptionsFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into ProtocolConfigurationOptionsFields.\nfunc (f *ProtocolConfigurationOptionsFields) UnmarshalBinary(b []byte) error {\n\tif len(b) < 1 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\tf.Extension = (b[0] >> 7) & 0x01\n\tf.ConfigurationProtocol = b[0] & 0x07\n\n\toffset := 1\n\tfor {\n\t\tif offset >= len(b) {\n\t\t\treturn nil\n\t\t}\n\t\topt, err := ParsePCOContainer(b[offset:])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.ProtocolOrContainers = append(f.ProtocolOrContainers, opt)\n\t\toffset += opt.MarshalLen()\n\t}\n}\n\n// MarshalLen returns the serial length of ProtocolConfigurationOptionsFields in int.\nfunc (f *ProtocolConfigurationOptionsFields) MarshalLen() int {\n\tl := 1\n\tfor _, opt := range f.ProtocolOrContainers {\n\t\tl += opt.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// ProtocolIdentifier definitions.\n//\n// [Table 10.5.154/3GPP TS 24.008]\n//\n// At least the following protocol identifiers (as defined in RFC 3232 [103]) shall be\n// supported in this version of the protocol:\n// - C021H (LCP);\n// - C023H (PAP);\n// - C223H (CHAP); and\n// - 8021H (IPCP).\nconst (\n\tPCOProtocolIdentifierLCP  uint16 = 0xc021\n\tPCOProtocolIdentifierPAP  uint16 = 0xc023\n\tPCOProtocolIdentifierCHAP uint16 = 0xc223\n\tPCOProtocolIdentifierIPCP uint16 = 0x8021\n)\n\n// PCOContainer is either of a Configuration protocol option or Additional parameters in PCO,\n// which are not distinguishable without meta information(link direction) but fortunately\n// the format is the same.\ntype PCOContainer struct {\n\tID       uint16\n\tLength   uint8\n\tContents []byte\n}\n\n// NewPCOContainer creates a new PCOContainer.\nfunc NewPCOContainer(pid uint16, contents []byte) *PCOContainer {\n\tc := &PCOContainer{\n\t\tID:       pid,\n\t\tLength:   uint8(len(contents)),\n\t\tContents: contents,\n\t}\n\treturn c\n}\n\n// Marshal serializes PCOContainer.\nfunc (c *PCOContainer) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes PCOContainer.\nfunc (c *PCOContainer) MarshalTo(b []byte) error {\n\tbinary.BigEndian.PutUint16(b[0:2], c.ID)\n\tb[2] = c.Length\n\tif c.Length != 0 {\n\t\tcopy(b[3:], c.Contents)\n\t}\n\n\treturn nil\n}\n\n// ParsePCOContainer decodes PCOContainer.\nfunc ParsePCOContainer(b []byte) (*PCOContainer, error) {\n\tc := &PCOContainer{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes into PCOContainer.\nfunc (c *PCOContainer) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn ErrTooShortToParse\n\t}\n\n\tc.ID = binary.BigEndian.Uint16(b[0:2])\n\tc.Length = b[2]\n\n\tif c.Length != 0 && l >= 3+int(c.Length) {\n\t\tc.Contents = make([]byte, c.Length)\n\t\tcopy(c.Contents, b[3:3+int(c.Length)])\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of PCOContainer in int.\nfunc (c *PCOContainer) MarshalLen() int {\n\treturn 3 + len(c.Contents)\n}\n"
  },
  {
    "path": "gtpv2/ie/pdn-type.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewPDNType creates a new PDNType IE.\nfunc NewPDNType(pdn uint8) *IE {\n\treturn NewUint8IE(PDNType, pdn)\n}\n\n// PDNType returns the PDNType value in uint8 if the type of IE matches.\nfunc (i *IE) PDNType() (uint8, error) {\n\tswitch i.Type {\n\tcase PDNType, PDNAddressAllocation:\n\t\treturn i.ValueAsUint8()\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustPDNType returns PDNType in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPDNType() uint8 {\n\tv, _ := i.PDNType()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/plmn-id.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewPLMNID creates a PLMNID IE.\nfunc NewPLMNID(mcc, mnc string) *IE {\n\tencoded, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(PLMNID, 0x00, encoded)\n}\n\n// PLMNID returns PLMNID(MCC and MNC) in string if the type of IE matches.\nfunc (i *IE) PLMNID() (string, error) {\n\tif i.Type != PLMNID {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tmcc, mnc, err := utils.DecodePLMN(i.Payload)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn mcc + mnc, nil\n}\n\n// MustPLMNID returns PLMNID in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPLMNID() string {\n\tv, _ := i.PLMNID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/port-number.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewPortNumber creates a new PortNumber IE.\nfunc NewPortNumber(port uint16) *IE {\n\treturn NewUint16IE(PortNumber, port)\n}\n\n// PortNumber returns PortNumber in uint16 if the type of IE matches.\nfunc (i *IE) PortNumber() (uint16, error) {\n\tswitch i.Type {\n\tcase PortNumber:\n\t\treturn i.ValueAsUint16()\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustPortNumber returns PortNumber in uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPortNumber() uint16 {\n\tv, _ := i.PortNumber()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/private-extension.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n)\n\n// NewPrivateExtension creates a new PrivateExtension IE.\nfunc NewPrivateExtension(id uint16, value []byte) *IE {\n\ti := New(PrivateExtension, 0x00, make([]byte, 2+len(value)))\n\tbinary.BigEndian.PutUint16(i.Payload[0:2], id)\n\tcopy(i.Payload[2:], value)\n\treturn i\n}\n\n// EnterpriseID returns EnterpriseID in uint16 if the type of IE matches.\nfunc (i *IE) EnterpriseID() (uint16, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(i.Payload[0:2]), nil\n\n}\n\n// MustEnterpriseID returns EnterpriseID in uint16, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustEnterpriseID() uint16 {\n\tv, _ := i.EnterpriseID()\n\treturn v\n}\n\n// PrivateExtension returns PrivateExtension value in []byte if the type of IE matches.\nfunc (i *IE) PrivateExtension() ([]byte, error) {\n\tif i.Type != PrivateExtension {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[2:], nil\n}\n\n// MustPrivateExtension returns PrivateExtension in []byte, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustPrivateExtension() []byte {\n\tv, _ := i.PrivateExtension()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/pti.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewProcedureTransactionID creates a new ProcedureTransactionID IE.\nfunc NewProcedureTransactionID(pti uint8) *IE {\n\treturn NewUint8IE(ProcedureTransactionID, pti)\n}\n\n// ProcedureTransactionID returns ProcedureTransactionID in uint8 if the type of IE matches.\nfunc (i *IE) ProcedureTransactionID() (uint8, error) {\n\tif i.Type != ProcedureTransactionID {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustProcedureTransactionID returns ProcedureTransactionID in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustProcedureTransactionID() uint8 {\n\tv, _ := i.ProcedureTransactionID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/ran-nas-cause.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// NewRANNASCause creates a new RANNASCause IE.\nfunc NewRANNASCause(pType, cType uint8, cause []byte) *IE {\n\tv := NewRANNASCauseFields(pType, cType, cause)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(RANNASCause, 0x00, b)\n}\n\n// RANNASCause returns RANNASCause in RANNASCauseFields type if the type of IE matches.\nfunc (i *IE) RANNASCause() (*RANNASCauseFields, error) {\n\tswitch i.Type {\n\tcase RANNASCause:\n\t\treturn ParseRANNASCauseFields(i.Payload)\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to retrieve RANNASCause: %w\", err)\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == RANNASCause {\n\t\t\t\treturn child.RANNASCause()\n\t\t\t}\n\t\t}\n\t\treturn nil, ErrIENotFound\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// RANNASCauseFields is a set of fields in RANNASCause IE.\ntype RANNASCauseFields struct {\n\tProtocolType uint8  // 4-bit\n\tCauseType    uint8  // 4-bit\n\tCause        []byte // format depends on ProtocolType\n}\n\n// NewRANNASCauseFields creates a new RANNASCauseFields.\nfunc NewRANNASCauseFields(pType, cType uint8, cause []byte) *RANNASCauseFields {\n\treturn &RANNASCauseFields{\n\t\tProtocolType: pType,\n\t\tCauseType:    cType,\n\t\tCause:        cause,\n\t}\n}\n\n// Marshal serializes RANNASCauseFields.\nfunc (f *RANNASCauseFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes RANNASCauseFields.\nfunc (f *RANNASCauseFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = ((f.ProtocolType & 0x0f) << 4) | (f.CauseType & 0x0f)\n\n\tif l < 1+len(f.Cause) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[1:], f.Cause)\n\n\treturn nil\n}\n\n// ParseRANNASCauseFields decodes RANNASCauseFields.\nfunc ParseRANNASCauseFields(b []byte) (*RANNASCauseFields, error) {\n\tf := &RANNASCauseFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into RANNASCauseFields.\nfunc (f *RANNASCauseFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.ProtocolType = (b[0] & 0xf0) >> 4\n\tf.CauseType = b[0] & 0x0f\n\tf.Cause = b[1:]\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of RANNASCauseFields in int.\nfunc (f *RANNASCauseFields) MarshalLen() int {\n\treturn 1 + len(f.Cause)\n}\n"
  },
  {
    "path": "gtpv2/ie/rat-type.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewRATType creates a new RATType IE.\nfunc NewRATType(rat uint8) *IE {\n\treturn NewUint8IE(RATType, rat)\n}\n\n// RATType returns RATType in uint8 if the type of IE matches.\nfunc (i *IE) RATType() (uint8, error) {\n\tswitch i.Type {\n\tcase RATType:\n\t\treturn i.ValueAsUint8()\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustRATType returns RATType in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRATType() uint8 {\n\tv, _ := i.RATType()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/recovery.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewRecovery creates a new Recovery IE.\nfunc NewRecovery(recovery uint8) *IE {\n\treturn NewUint8IE(Recovery, recovery)\n}\n\n// Recovery returns Recovery value if the type of IE matches.\nfunc (i *IE) Recovery() (uint8, error) {\n\tif i.Type != Recovery {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustRecovery returns Recovery in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRecovery() uint8 {\n\tv, _ := i.Recovery()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/rfsp-index.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewRFSPIndex creates a new RFSPIndex IE.\nfunc NewRFSPIndex(idx uint8) *IE {\n\treturn NewUint8IE(RFSPIndex, idx)\n}\n\n// RFSPIndex returns RFSPIndex in uint8 if the type of IE matches.\nfunc (i *IE) RFSPIndex() (uint8, error) {\n\tif i.Type != RFSPIndex {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustRFSPIndex returns RFSPIndex in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustRFSPIndex() uint8 {\n\tv, _ := i.RFSPIndex()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/s103pdf.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"net\"\n)\n\n// NewS103PDNDataForwardingInfo creates a new S103PDNDataForwardingInfo IE.\nfunc NewS103PDNDataForwardingInfo(hsgwAddr string, greKey uint32, ebis ...uint8) *IE {\n\tv := NewS103PDNDataForwardingInfoFields(net.ParseIP(hsgwAddr), greKey, ebis...)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(S103PDNDataForwardingInfo, 0x00, b)\n}\n\n// NewS103PDNDataForwardingInfoNetIP creates a new S103PDNDataForwardingInfo IE.\nfunc NewS103PDNDataForwardingInfoNetIP(hsgwIP net.IP, greKey uint32, ebis ...uint8) *IE {\n\tv := NewS103PDNDataForwardingInfoFields(hsgwIP, greKey, ebis...)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(S103PDNDataForwardingInfo, 0x00, b)\n}\n\n// S103PDNDataForwardingInfo returns S103PDNDataForwardingInfo in S103PDNDataForwardingInfoFields type if the type of IE matches.\nfunc (i *IE) S103PDNDataForwardingInfo() (*S103PDNDataForwardingInfoFields, error) {\n\tswitch i.Type {\n\tcase S103PDNDataForwardingInfo:\n\t\treturn ParseS103PDNDataForwardingInfoFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// S103PDNDataForwardingInfoFields is a set of fields in S103PDNDataForwardingInfo IE.\ntype S103PDNDataForwardingInfoFields struct {\n\tHSGWAddressForForwardingLength uint8\n\tHSGWAddressForForwarding       net.IP\n\tGREKey                         uint32\n\tEPSBearerIDNumber              uint8\n\tEPSBearerIDs                   []uint8\n}\n\n// NewS103PDNDataForwardingInfoFields creates a new S103PDNDataForwardingInfoFields.\nfunc NewS103PDNDataForwardingInfoFields(hsgwIP net.IP, greKey uint32, ebis ...uint8) *S103PDNDataForwardingInfoFields {\n\tf := &S103PDNDataForwardingInfoFields{\n\t\tGREKey:            greKey,\n\t\tEPSBearerIDNumber: uint8(len(ebis)),\n\t\tEPSBearerIDs:      ebis,\n\t}\n\n\tif v := hsgwIP.To4(); v != nil {\n\t\tf.HSGWAddressForForwardingLength = 4\n\t\tf.HSGWAddressForForwarding = v\n\t\treturn f\n\t}\n\n\tif v := hsgwIP.To16(); v != nil {\n\t\tf.HSGWAddressForForwardingLength = 16\n\t\tf.HSGWAddressForForwarding = v\n\t\treturn f\n\t}\n\n\t// return IE w/ \"something\" anyway\n\tf.HSGWAddressForForwardingLength = uint8(len(hsgwIP))\n\tf.HSGWAddressForForwarding = hsgwIP\n\treturn f\n}\n\n// Marshal serializes S103PDNDataForwardingInfoFields.\nfunc (f *S103PDNDataForwardingInfoFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes S103PDNDataForwardingInfoFields.\nfunc (f *S103PDNDataForwardingInfoFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.HSGWAddressForForwardingLength\n\toffset := 1\n\n\tif l < offset+int(f.HSGWAddressForForwardingLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+int(f.HSGWAddressForForwardingLength)], f.HSGWAddressForForwarding)\n\toffset += int(f.HSGWAddressForForwardingLength)\n\n\tif l < offset+4 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tbinary.BigEndian.PutUint32(b[offset:offset+4], f.GREKey)\n\toffset += 4\n\n\tb[offset] = f.EPSBearerIDNumber\n\toffset++\n\n\tif l < offset+int(f.EPSBearerIDNumber) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tfor _, ebi := range f.EPSBearerIDs {\n\t\tb[offset] = ebi & 0x0f\n\t\toffset++\n\t}\n\n\treturn nil\n}\n\n// ParseS103PDNDataForwardingInfoFields decodes S103PDNDataForwardingInfoFields.\nfunc ParseS103PDNDataForwardingInfoFields(b []byte) (*S103PDNDataForwardingInfoFields, error) {\n\tf := &S103PDNDataForwardingInfoFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into S103PDNDataForwardingInfoFields.\nfunc (f *S103PDNDataForwardingInfoFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.HSGWAddressForForwardingLength = b[0]\n\toffset := 1\n\n\tif l < offset+int(f.HSGWAddressForForwardingLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tf.HSGWAddressForForwarding = net.IP(b[offset : offset+int(f.HSGWAddressForForwardingLength)])\n\toffset += int(f.HSGWAddressForForwardingLength)\n\n\tif l < offset+4 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tf.GREKey = binary.BigEndian.Uint32(b[offset : offset+4])\n\toffset += 4\n\n\tif l <= offset {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.EPSBearerIDNumber = b[offset]\n\toffset++\n\n\tif l < offset+int(f.EPSBearerIDNumber) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.EPSBearerIDs = make([]uint8, f.EPSBearerIDNumber)\n\tfor n := 0; n < int(f.EPSBearerIDNumber); n++ {\n\t\tf.EPSBearerIDs[n] = b[offset]\n\t\toffset++\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of S103PDNDataForwardingInfoFields in int.\nfunc (f *S103PDNDataForwardingInfoFields) MarshalLen() int {\n\treturn 1 + int(f.HSGWAddressForForwardingLength) + 4 + 1 + int(f.EPSBearerIDNumber)\n}\n\n// HSGWAddress returns IP address of HSGW in string if the type of IE matches.\nfunc (i *IE) HSGWAddress() (string, error) {\n\tif i.Type != S103PDNDataForwardingInfo {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\n\treturn i.IPAddress()\n}\n\n// MustHSGWAddress returns HSGWAddress in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustHSGWAddress() string {\n\tv, _ := i.HSGWAddress()\n\treturn v\n}\n\n// EBIs returns the EBIs in []uint8 if the type of IE matches.\nfunc (i *IE) EBIs() ([]uint8, error) {\n\tif i.Type != S103PDNDataForwardingInfo {\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tvar n, offset int\n\tswitch i.Payload[0] {\n\tcase 4:\n\t\tif len(i.Payload) <= 9 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\tn = int(i.Payload[9])\n\t\toffset = 10\n\tcase 16:\n\t\tif len(i.Payload) <= 21 {\n\t\t\treturn nil, io.ErrUnexpectedEOF\n\t\t}\n\t\tn = int(i.Payload[21])\n\t\toffset = 22\n\tdefault:\n\t\treturn nil, ErrMalformed\n\t}\n\n\tvar ebis []uint8\n\tfor x := 0; x < n; x++ {\n\t\tif len(i.Payload) <= offset+x {\n\t\t\tbreak\n\t\t}\n\t\tebis = append(ebis, i.Payload[offset+x])\n\t}\n\treturn ebis, nil\n}\n\n// MustEBIs returns EBIs in []uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustEBIs() []uint8 {\n\tv, _ := i.EBIs()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/s1udf.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"net\"\n)\n\n// NewS1UDataForwarding creates a new S1UDataForwarding IE.\nfunc NewS1UDataForwarding(ebi uint8, sgwAddr string, sgwTEID uint32) *IE {\n\tv := NewS1UDataForwardingFields(ebi, net.ParseIP(sgwAddr), sgwTEID)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(S1UDataForwarding, 0x00, b)\n}\n\n// NewS1UDataForwardingNetIP creates a new S1UDataForwarding IE.\nfunc NewS1UDataForwardingNetIP(ebi uint8, sgwIP net.IP, sgwTEID uint32) *IE {\n\tv := NewS1UDataForwardingFields(ebi, sgwIP, sgwTEID)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(S1UDataForwarding, 0x00, b)\n}\n\n// S1UDataForwarding returns S1UDataForwarding in S1UDataForwardingFields type if the type of IE matches.\nfunc (i *IE) S1UDataForwarding() (*S1UDataForwardingFields, error) {\n\tswitch i.Type {\n\tcase S1UDataForwarding:\n\t\treturn ParseS1UDataForwardingFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// S1UDataForwardingFields is a set of fields in S1UDataForwarding IE.\ntype S1UDataForwardingFields struct {\n\tEPSBearerID            uint8 // 4-bit\n\tServingGWAddressLength uint8\n\tServingGWAddress       net.IP\n\tServingGWS1UTEID       uint32\n}\n\n// NewS1UDataForwardingFields creates a new S1UDataForwardingFields.\nfunc NewS1UDataForwardingFields(ebi uint8, sgwAddr net.IP, sgwTEID uint32) *S1UDataForwardingFields {\n\tf := &S1UDataForwardingFields{\n\t\tEPSBearerID:      ebi,\n\t\tServingGWS1UTEID: sgwTEID,\n\t}\n\n\tif v := sgwAddr.To4(); v != nil {\n\t\tf.ServingGWAddressLength = 4\n\t\tf.ServingGWAddress = v\n\t\treturn f\n\t}\n\n\tif v := sgwAddr.To16(); v != nil {\n\t\tf.ServingGWAddressLength = 16\n\t\tf.ServingGWAddress = v\n\t\treturn f\n\t}\n\n\t// return IE w/ \"something\" anyway\n\tf.ServingGWAddressLength = uint8(len(sgwAddr))\n\tf.ServingGWAddress = sgwAddr\n\treturn f\n}\n\n// Marshal serializes S1UDataForwardingFields.\nfunc (f *S1UDataForwardingFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes S1UDataForwardingFields.\nfunc (f *S1UDataForwardingFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.EPSBearerID & 0x0f\n\tb[1] = f.ServingGWAddressLength\n\toffset := 2\n\n\tif l < offset+int(f.ServingGWAddressLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+int(f.ServingGWAddressLength)], f.ServingGWAddress)\n\toffset += int(f.ServingGWAddressLength)\n\n\tif l < offset+4 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tbinary.BigEndian.PutUint32(b[offset:offset+4], f.ServingGWS1UTEID)\n\n\treturn nil\n}\n\n// ParseS1UDataForwardingFields decodes S1UDataForwardingFields.\nfunc ParseS1UDataForwardingFields(b []byte) (*S1UDataForwardingFields, error) {\n\tf := &S1UDataForwardingFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into S1UDataForwardingFields.\nfunc (f *S1UDataForwardingFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.EPSBearerID = b[0] & 0x0f\n\tf.ServingGWAddressLength = b[1]\n\toffset := 2\n\n\tif l < offset+int(f.ServingGWAddressLength) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tf.ServingGWAddress = net.IP(b[offset : offset+int(f.ServingGWAddressLength)])\n\toffset += int(f.ServingGWAddressLength)\n\n\tif l < offset+4 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tf.ServingGWS1UTEID = binary.BigEndian.Uint32(b[offset : offset+4])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of S1UDataForwardingFields in int.\nfunc (f *S1UDataForwardingFields) MarshalLen() int {\n\treturn 2 + int(f.ServingGWAddressLength) + 4\n}\n\n// SGWAddress returns IP address of SGW in string if the type of IE matches.\nfunc (i *IE) SGWAddress() (string, error) {\n\tif i.Type != S1UDataForwarding {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\n\treturn i.IPAddress()\n}\n\n// MustSGWAddress returns SGWAddress in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustSGWAddress() string {\n\tv, _ := i.SGWAddress()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/selection-mode.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewSelectionMode creates a new SelectionMode IE.\nfunc NewSelectionMode(mode uint8) *IE {\n\treturn NewUint8IE(SelectionMode, mode)\n}\n\n// SelectionMode returns SelectionMode value if the type of IE matches.\nfunc (i *IE) SelectionMode() (uint8, error) {\n\tif i.Type != SelectionMode {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustSelectionMode returns SelectionMode in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustSelectionMode() uint8 {\n\tv, _ := i.SelectionMode()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/service-indicator.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewServiceIndicator creates a new ServiceIndicator IE.\nfunc NewServiceIndicator(ind uint8) *IE {\n\treturn NewUint8IE(ServiceIndicator, ind)\n}\n\n// ServiceIndicator returns ServiceIndicator in uint8 if the type of IE matches.\nfunc (i *IE) ServiceIndicator() (uint8, error) {\n\tif i.Type != ServiceIndicator {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\treturn i.ValueAsUint8()\n}\n\n// MustServiceIndicator returns ServiceIndicator in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustServiceIndicator() uint8 {\n\tv, _ := i.ServiceIndicator()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/serving-nw.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewServingNetwork creates a ServingNetwork IE.\nfunc NewServingNetwork(mcc, mnc string) *IE {\n\tencoded, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(ServingNetwork, 0x00, encoded)\n}\n\n// ServingNetwork returns ServingNetwork(MCC and MNC) in string if the type of IE matches.\nfunc (i *IE) ServingNetwork() (string, error) {\n\tif i.Type != ServingNetwork {\n\t\treturn \"\", &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 3 {\n\t\treturn \"\", io.ErrUnexpectedEOF\n\t}\n\n\tmcc, mnc, err := utils.DecodePLMN(i.Payload)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn mcc + mnc, nil\n}\n\n// MustServingNetwork returns ServingNetwork in string, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustServingNetwork() string {\n\tv, _ := i.ServingNetwork()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/tad.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewTrafficAggregateDescription creates a new TrafficAggregateDescription IE.\n//\n// Custom constructors for each operation code are available, which does not require\n// unnecessary parameters.\nfunc NewTrafficAggregateDescription(op uint8, filters []*TFTPacketFilter, ids []uint8, params []*TFTParameter) *IE {\n\tv := NewTrafficFlowTemplate(op, filters, ids, params)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(TrafficAggregateDescription, 0x00, b)\n}\n\n// NewTrafficAggregateDescriptionCreateNewTFT creates a new TrafficAggregateDescription IE with opcode=CreateNewTFT.\nfunc NewTrafficAggregateDescriptionCreateNewTFT(filters []*TFTPacketFilter, params []*TFTParameter) *IE {\n\treturn NewTrafficAggregateDescription(TFTOpCreateNewTFT, filters, nil, params)\n}\n\n// NewTrafficAggregateDescriptionAddPacketFilters creates a new TrafficAggregateDescription IE with opcode=AddPacketFiltersToExistingTFT.\nfunc NewTrafficAggregateDescriptionAddPacketFilters(filters []*TFTPacketFilter, params []*TFTParameter) *IE {\n\treturn NewTrafficAggregateDescription(TFTOpAddPacketFiltersToExistingTFT, filters, nil, params)\n}\n\n// NewTrafficAggregateDescriptionReplacePacketFilters creates a new TrafficAggregateDescription IE with opcode=ReplacePacketFiltersInExistingTFT.\nfunc NewTrafficAggregateDescriptionReplacePacketFilters(filters []*TFTPacketFilter, params []*TFTParameter) *IE {\n\treturn NewTrafficAggregateDescription(TFTOpReplacePacketFiltersInExistingTFT, filters, nil, params)\n}\n\n// NewTrafficAggregateDescriptionDeletePacketFilters creates a new TrafficAggregateDescription IE with opcode=DeletePacketFiltersFromExistingTFT.\nfunc NewTrafficAggregateDescriptionDeletePacketFilters(ids []uint8, params ...*TFTParameter) *IE {\n\treturn NewTrafficAggregateDescription(TFTOpDeletePacketFiltersFromExistingTFT, nil, ids, params)\n}\n\n// NewTrafficAggregateDescriptionDeleteExistingTFT creates a new TrafficAggregateDescription IE with opcode=DeleteExistingTFT.\nfunc NewTrafficAggregateDescriptionDeleteExistingTFT(params ...*TFTParameter) *IE {\n\treturn NewTrafficAggregateDescription(TFTOpDeleteExistingTFT, nil, nil, params)\n}\n\n// NewTrafficAggregateDescriptionNoTFTOperation creates a new TrafficAggregateDescription IE with opcode=NoTFTOperation.\nfunc NewTrafficAggregateDescriptionNoTFTOperation(params ...*TFTParameter) *IE {\n\treturn NewTrafficAggregateDescription(TFTOpNoTFTOperation, nil, nil, params)\n}\n\n// TrafficAggregateDescription returns TrafficAggregateDescription in TrafficFlowTemplate type if the type of IE matches.\nfunc (i *IE) TrafficAggregateDescription() (*TrafficFlowTemplate, error) {\n\treturn i.TrafficFlowTemplate()\n}\n"
  },
  {
    "path": "gtpv2/ie/tft.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// TrafficFlowTemplate returns TrafficFlowTemplate struct if the type of IE matches.\nfunc (i *IE) TrafficFlowTemplate() (*TrafficFlowTemplate, error) {\n\tswitch i.Type {\n\tcase BearerTFT, TrafficAggregateDescription:\n\t\treturn ParseTrafficFlowTemplate(i.Payload)\n\tcase BearerContext:\n\t\ties, err := i.BearerContext()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to retrieve BearerContext: %w\", err)\n\t\t}\n\n\t\tfor _, child := range ies {\n\t\t\tif child.Type == BearerTFT {\n\t\t\t\treturn child.TrafficFlowTemplate()\n\t\t\t}\n\t\t}\n\t\treturn nil, ErrIENotFound\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// TrafficFlowTemplate is a set of fields in BearerTFT IE.\ntype TrafficFlowTemplate struct {\n\tOperationCode           uint8\n\tPacketFilters           []*TFTPacketFilter\n\tPacketFilterIdentifiers []uint8\n\tParameters              []*TFTParameter\n}\n\n// NewTrafficFlowTemplate creates a new TrafficFlowTemplate.\nfunc NewTrafficFlowTemplate(op uint8, filters []*TFTPacketFilter, ids []uint8, params []*TFTParameter) *TrafficFlowTemplate {\n\tvar fs []*TFTPacketFilter\n\tfor _, f := range filters {\n\t\tif f != nil {\n\t\t\tfs = append(fs, f)\n\t\t}\n\t}\n\n\tvar ps []*TFTParameter\n\tfor _, p := range params {\n\t\tif p != nil {\n\t\t\tps = append(ps, p)\n\t\t}\n\t}\n\n\treturn &TrafficFlowTemplate{\n\t\tOperationCode:           op,\n\t\tPacketFilters:           fs,\n\t\tPacketFilterIdentifiers: ids,\n\t\tParameters:              ps,\n\t}\n}\n\n// Marshal serializes TrafficFlowTemplate.\nfunc (f *TrafficFlowTemplate) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes TrafficFlowTemplate.\nfunc (f *TrafficFlowTemplate) MarshalTo(b []byte) error {\n\tif len(b) < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\t// 000. .... = TFT operation code\n\t// ...0 .... = E bit\n\t// .... 0000 = Number of packet filters\n\top := (f.OperationCode & 0b111) << 5\n\te := uint8(len(f.Parameters)*1&0b1) << 4\n\tpf := len(f.PacketFilters)\n\tif f.OperationCode == TFTOpDeletePacketFiltersFromExistingTFT {\n\t\tpf = len(f.PacketFilterIdentifiers)\n\t}\n\tb[0] = op | e | uint8(pf&0b1111)\n\n\toffset := 1\n\tswitch f.OperationCode {\n\tcase TFTOpCreateNewTFT,\n\t\tTFTOpAddPacketFiltersToExistingTFT,\n\t\tTFTOpReplacePacketFiltersInExistingTFT:\n\t\tfor _, filter := range f.PacketFilters {\n\t\t\tif filter == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := filter.MarshalTo(b[offset:]); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to marshal Packet Filter: %w\", err)\n\t\t\t}\n\t\t\toffset += filter.MarshalLen()\n\t\t}\n\tcase TFTOpDeletePacketFiltersFromExistingTFT:\n\t\tcopy(b[offset:offset+pf], f.PacketFilterIdentifiers)\n\t\toffset += pf\n\t}\n\n\tfor _, param := range f.Parameters {\n\t\tif param == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := param.MarshalTo(b[offset:]); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal Parameter: %w\", err)\n\t\t}\n\t\toffset += param.MarshalLen()\n\t}\n\n\treturn nil\n}\n\n// ParseTrafficFlowTemplate decodes TrafficFlowTemplate.\nfunc ParseTrafficFlowTemplate(b []byte) (*TrafficFlowTemplate, error) {\n\tf := &TrafficFlowTemplate{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into TrafficFlowTemplate.\nfunc (f *TrafficFlowTemplate) UnmarshalBinary(b []byte) error {\n\tif len(b) < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.OperationCode = b[0] >> 5\n\thasParams := (b[0] >> 4 & 0b1) == 1\n\tfilterLen := int(b[0] & 0b1111)\n\n\toffset := 1\n\tswitch f.OperationCode {\n\tcase TFTOpCreateNewTFT,\n\t\tTFTOpAddPacketFiltersToExistingTFT,\n\t\tTFTOpReplacePacketFiltersInExistingTFT:\n\t\tf.PacketFilters = []*TFTPacketFilter{}\n\t\tfor i := 0; i < filterLen; i++ {\n\t\t\tfilter, err := ParseTFTPacketFilter(b[offset:])\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to parse Packet Filter: %w\", err)\n\t\t\t}\n\t\t\tf.PacketFilters = append(f.PacketFilters, filter)\n\t\t\toffset += filter.MarshalLen()\n\t\t}\n\tcase TFTOpDeletePacketFiltersFromExistingTFT:\n\t\tif len(b) < offset+filterLen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.PacketFilterIdentifiers = b[offset : offset+filterLen]\n\t\toffset += filterLen\n\t}\n\n\tif hasParams {\n\t\tparams, err := ParseMultiTFTParameters(b[offset:])\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to parse Parameters: %w\", err)\n\t\t}\n\t\tf.Parameters = params\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of TrafficFlowTemplate in int.\nfunc (f *TrafficFlowTemplate) MarshalLen() int {\n\tl := 1\n\n\tfor _, filter := range f.PacketFilters {\n\t\tif filter == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += filter.MarshalLen()\n\t}\n\n\tl += len(f.PacketFilterIdentifiers)\n\n\tfor _, param := range f.Parameters {\n\t\tif param == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += param.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// TFT Packet Filter Identifier definitions.\nconst (\n\tTFTPFPreRel7TFTFilter uint8 = 0\n\tTFTPFDownlinkOnly     uint8 = 1\n\tTFTPFUplinkOnly       uint8 = 2\n\tTFTPFBidirectional    uint8 = 3\n)\n\n// TFTPacketFilter represents a PacketFilter in TFT.\ntype TFTPacketFilter struct {\n\tDirection            uint8\n\tIdentifier           uint8\n\tEvaluationPrecedence uint8\n\tLength               uint8\n\tComponents           []*TFTPFComponent\n}\n\n// NewTFTPacketFilter creates a new TFTPacketFilter.\nfunc NewTFTPacketFilter(dir, id, precedence uint8, comps ...*TFTPFComponent) *TFTPacketFilter {\n\tpf := &TFTPacketFilter{\n\t\tDirection:            dir,\n\t\tIdentifier:           id,\n\t\tEvaluationPrecedence: precedence,\n\t\tComponents:           comps,\n\t}\n\tpf.SetLength()\n\n\treturn pf\n}\n\n// Marshal serializes TFTPacketFilter.\nfunc (p *TFTPacketFilter) Marshal() ([]byte, error) {\n\tb := make([]byte, p.MarshalLen())\n\tif err := p.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes TFTPacketFilter into b.\nfunc (p *TFTPacketFilter) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = (p.Direction&0b11)<<4 | p.Identifier&0b1111\n\tb[1] = p.EvaluationPrecedence\n\tb[2] = p.Length\n\toffset := 3\n\n\tfor _, comp := range p.Components {\n\t\tn := comp.MarshalLen()\n\t\tif l < offset+n {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tif err := comp.MarshalTo(b[offset : offset+n]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += n\n\t}\n\n\treturn nil\n}\n\n// ParseTFTPacketFilter decodes TFTPacketFilter.\nfunc ParseTFTPacketFilter(b []byte) (*TFTPacketFilter, error) {\n\tp := &TFTPacketFilter{}\n\tif err := p.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn p, nil\n}\n\n// UnmarshalBinary decodes given bytes into TFTPacketFilter.\nfunc (p *TFTPacketFilter) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tp.Direction = (b[0] >> 4) & 0b11\n\tp.Identifier = b[0] & 0b1111\n\tp.EvaluationPrecedence = b[1]\n\tp.Length = b[2]\n\toffset := 3\n\n\tn := offset + int(p.Length)\n\tif l < n {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcomps, err := ParseMultiTFTPFComponent(b[offset:n])\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.Components = comps\n\n\treturn nil\n}\n\n// SetLength sets the length in TFTPacketFilter.\nfunc (p *TFTPacketFilter) SetLength() {\n\tl := 0\n\tfor _, comp := range p.Components {\n\t\tl += comp.MarshalLen()\n\t}\n\n\tp.Length = uint8(l)\n}\n\n// MarshalLen returns the serial length of TFTPacketFilter in int.\nfunc (p *TFTPacketFilter) MarshalLen() int {\n\tl := 3\n\n\tfor _, comp := range p.Components {\n\t\tl += comp.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// Packet Filter Component Type definitions.\nconst (\n\tPFCompIPv4RemoteAddress             uint8 = 0b00010000\n\tPFCompIPv4LocalAddress              uint8 = 0b00010001\n\tPFCompIPv6RemoteAddress             uint8 = 0b00100000\n\tPFCompIPv6RemoteAddressPrefixLength uint8 = 0b00100001\n\tPFCompIPv6LocalAddressPrefixLength  uint8 = 0b00100011\n\tPFCompProtocolIdentifierNextHeader  uint8 = 0b00110000\n\tPFCompSingleLocalPort               uint8 = 0b01000000\n\tPFCompLocalPortRange                uint8 = 0b01000001\n\tPFCompSingleRemotePort              uint8 = 0b01010000\n\tPFCompRemotePortRange               uint8 = 0b01010001\n\tPFCompSecurityParameterIndex        uint8 = 0b01100000\n\tPFCompTypeOfServiceTrafficClass     uint8 = 0b01110000\n\tPFCompFlowLabel                     uint8 = 0b10000000\n\tPFCompDestinationMACAddress         uint8 = 0b10000001\n\tPFCompSourceMACAddress              uint8 = 0b10000010\n\tPFCompDot1QCTAGVID                  uint8 = 0b10000011\n\tPFCompDot1QSTAGVID                  uint8 = 0b10000100\n\tPFCompDot1QCTAGPCPDEI               uint8 = 0b10000101\n\tPFCompDot1QSTAGPCPDEI               uint8 = 0b10000110\n\tPFCompEthertype                     uint8 = 0b10000111\n)\n\n// TFTPFComponent represents a component in Packet Fileter in TFT.\ntype TFTPFComponent struct {\n\tType     uint8\n\tContents []byte\n}\n\n// NewTFTPFComponent creates a new TFTPFComponent.\nfunc NewTFTPFComponent(t uint8, contents []byte) *TFTPFComponent {\n\treturn &TFTPFComponent{\n\t\tType:     t,\n\t\tContents: contents,\n\t}\n}\n\n// NewTFTPFComponentIPv4RemoteAddress creates a new TFTPFComponent of type IPv4RemoteAddress.\nfunc NewTFTPFComponentIPv4RemoteAddress(ip net.IP, mask net.IPMask) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompIPv4RemoteAddress, append(ip.To4(), mask...))\n}\n\n// NewTFTPFComponentIPv4LocalAddress creates a new TFTPFComponent of type IPv4LocalAddress.\nfunc NewTFTPFComponentIPv4LocalAddress(ip net.IP, mask net.IPMask) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompIPv4LocalAddress, append(ip.To4(), mask...))\n}\n\n// NewTFTPFComponentIPv6RemoteAddress creates a new TFTPFComponent of type IPv6RemoteAddress.\nfunc NewTFTPFComponentIPv6RemoteAddress(ip net.IP, mask net.IPMask) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompIPv6RemoteAddress, append(ip.To16(), mask...))\n}\n\n// NewTFTPFComponentIPv6RemoteAddressPrefixLength creates a new TFTPFComponent of type IPv6RemoteAddressPrefixLength.\nfunc NewTFTPFComponentIPv6RemoteAddressPrefixLength(ip net.IP, prefix uint8) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompIPv6RemoteAddressPrefixLength, append(ip.To16(), prefix))\n}\n\n// NewTFTPFComponentIPv6LocalAddressPrefixLength creates a new TFTPFComponent of type IPv6LocalAddressPrefixLength.\nfunc NewTFTPFComponentIPv6LocalAddressPrefixLength(ip net.IP, prefix uint8) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompIPv6LocalAddressPrefixLength, append(ip.To16(), prefix))\n}\n\n// NewTFTPFComponentProtocolIdentifierNextHeader creates a new TFTPFComponent of type ProtocolIdentifierNextHeader.\nfunc NewTFTPFComponentProtocolIdentifierNextHeader(id uint8) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompProtocolIdentifierNextHeader, []byte{id})\n}\n\n// NewTFTPFComponentSingleLocalPort creates a new TFTPFComponent of type SingleLocalPort.\nfunc NewTFTPFComponentSingleLocalPort(port uint16) *TFTPFComponent {\n\tb := make([]byte, 2)\n\tbinary.BigEndian.PutUint16(b, port)\n\treturn NewTFTPFComponent(PFCompSingleLocalPort, b)\n}\n\n// NewTFTPFComponentLocalPortRange creates a new TFTPFComponent of type LocalPortRange.\nfunc NewTFTPFComponentLocalPortRange(low, high uint16) *TFTPFComponent {\n\tb := make([]byte, 4)\n\tbinary.BigEndian.PutUint16(b[0:2], low)\n\tbinary.BigEndian.PutUint16(b[2:4], high)\n\treturn NewTFTPFComponent(PFCompLocalPortRange, b)\n}\n\n// NewTFTPFComponentSingleRemotePort creates a new TFTPFComponent of type SingleRemotePort.\nfunc NewTFTPFComponentSingleRemotePort(port uint16) *TFTPFComponent {\n\tb := make([]byte, 2)\n\tbinary.BigEndian.PutUint16(b, port)\n\treturn NewTFTPFComponent(PFCompSingleRemotePort, b)\n}\n\n// NewTFTPFComponentRemotePortRange creates a new TFTPFComponent of type RemotePortRange.\nfunc NewTFTPFComponentRemotePortRange(low, high uint16) *TFTPFComponent {\n\tb := make([]byte, 4)\n\tbinary.BigEndian.PutUint16(b[0:2], low)\n\tbinary.BigEndian.PutUint16(b[2:4], high)\n\treturn NewTFTPFComponent(PFCompRemotePortRange, b)\n}\n\n// NewTFTPFComponentSecurityParameterIndex creates a new TFTPFComponent of type SecurityParameterIndex.\nfunc NewTFTPFComponentSecurityParameterIndex(idx uint32) *TFTPFComponent {\n\tb := make([]byte, 4)\n\tbinary.BigEndian.PutUint32(b, idx)\n\treturn NewTFTPFComponent(PFCompSecurityParameterIndex, b)\n}\n\n// NewTFTPFComponentTypeOfServiceTrafficClass creates a new TFTPFComponent of type TypeOfServiceTrafficClass.\nfunc NewTFTPFComponentTypeOfServiceTrafficClass(class, mask uint8) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompTypeOfServiceTrafficClass, []byte{class, mask})\n}\n\n// NewTFTPFComponentFlowLabel creates a new TFTPFComponent of type FlowLabel.\nfunc NewTFTPFComponentFlowLabel(label uint32) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompFlowLabel, utils.Uint32To24(label))\n}\n\n// NewTFTPFComponentDestinationMACAddress creates a new TFTPFComponent of type DestinationMACAddress.\nfunc NewTFTPFComponentDestinationMACAddress(mac net.HardwareAddr) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompDestinationMACAddress, mac)\n}\n\n// NewTFTPFComponentSourceMACAddress creates a new TFTPFComponent of type SourceMACAddress.\nfunc NewTFTPFComponentSourceMACAddress(mac net.HardwareAddr) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompSourceMACAddress, mac)\n}\n\n// NewTFTPFComponentDot1QCTAGVID creates a new TFTPFComponent of type Dot1QCTAGVID.\nfunc NewTFTPFComponentDot1QCTAGVID(vid uint16) *TFTPFComponent {\n\tb := make([]byte, 2)\n\tbinary.BigEndian.PutUint16(b, vid)\n\treturn NewTFTPFComponent(PFCompDot1QCTAGVID, b)\n}\n\n// NewTFTPFComponentDot1QSTAGVID creates a new TFTPFComponent of type Dot1QSTAGVID.\nfunc NewTFTPFComponentDot1QSTAGVID(vid uint16) *TFTPFComponent {\n\tb := make([]byte, 2)\n\tbinary.BigEndian.PutUint16(b, vid)\n\treturn NewTFTPFComponent(PFCompDot1QSTAGVID, b)\n}\n\n// NewTFTPFComponentDot1QCTAGPCPDEI creates a new TFTPFComponent of type Dot1QCTAGPCPDEI.\nfunc NewTFTPFComponentDot1QCTAGPCPDEI(pcpdei uint8) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompDot1QCTAGPCPDEI, []byte{pcpdei})\n}\n\n// NewTFTPFComponentDot1QSTAGPCPDEI creates a new TFTPFComponent of type Dot1QSTAGPCPDEI.\nfunc NewTFTPFComponentDot1QSTAGPCPDEI(pcpdei uint8) *TFTPFComponent {\n\treturn NewTFTPFComponent(PFCompDot1QSTAGPCPDEI, []byte{pcpdei})\n}\n\n// NewTFTPFComponentEthertype creates a new TFTPFComponent of type Ethertype.\nfunc NewTFTPFComponentEthertype(etype uint16) *TFTPFComponent {\n\tb := make([]byte, 2)\n\tbinary.BigEndian.PutUint16(b, etype)\n\treturn NewTFTPFComponent(PFCompEthertype, b)\n}\n\n// IPv4RemoteAddress returns IPv4RemoteAddress in net.IPNet if the type of component matches.\nfunc (c *TFTPFComponent) IPv4RemoteAddress() (*net.IPNet, error) {\n\tif c.Type != PFCompIPv4RemoteAddress {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 8 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn &net.IPNet{IP: c.Contents[:4], Mask: c.Contents[4:8]}, nil\n}\n\n// IPv4LocalAddress returns IPv4LocalAddress in net.IPNet if the type of component matches.\nfunc (c *TFTPFComponent) IPv4LocalAddress() (*net.IPNet, error) {\n\tif c.Type != PFCompIPv4LocalAddress {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 8 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn &net.IPNet{IP: c.Contents[:4], Mask: c.Contents[4:8]}, nil\n}\n\n// IPv6RemoteAddress returns IPv6RemoteAddress in net.IPNet if the type of component matches.\nfunc (c *TFTPFComponent) IPv6RemoteAddress() (*net.IPNet, error) {\n\tif c.Type != PFCompIPv6RemoteAddress {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 32 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn &net.IPNet{IP: c.Contents[:16], Mask: c.Contents[17:32]}, nil\n}\n\n// IPv6RemoteAddressPrefixLength returns IPv6RemoteAddressPrefixLength in *net.IPNet\n// if the type of component matches.\nfunc (c *TFTPFComponent) IPv6RemoteAddressPrefixLength() (*net.IPNet, error) {\n\tif c.Type != PFCompIPv6RemoteAddressPrefixLength {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 17 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tipnet := &net.IPNet{\n\t\tIP:   net.IP(c.Contents[:16]),\n\t\tMask: net.CIDRMask(int(c.Contents[17]), 128),\n\t}\n\treturn ipnet, nil\n}\n\n// IPv6LocalAddressPrefixLength returns IPv6LocalAddressPrefixLength in *net.IPNet\n// if the type of component matches.\nfunc (c *TFTPFComponent) IPv6LocalAddressPrefixLength() (*net.IPNet, error) {\n\tif c.Type != PFCompIPv6LocalAddressPrefixLength {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 17 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tipnet := &net.IPNet{\n\t\tIP:   net.IP(c.Contents[:16]),\n\t\tMask: net.CIDRMask(int(c.Contents[17]), 128),\n\t}\n\treturn ipnet, nil\n}\n\n// ProtocolIdentifierNextHeader returns ProtocolIdentifierNextHeader in uint8\n// if the type of component matches.\nfunc (c *TFTPFComponent) ProtocolIdentifierNextHeader() (uint8, error) {\n\tif c.Type != PFCompProtocolIdentifierNextHeader {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn c.Contents[0], nil\n}\n\n// SingleLocalPort returns SingleLocalPort in uint16 if the type of component matches.\nfunc (c *TFTPFComponent) SingleLocalPort() (uint16, error) {\n\tif c.Type != PFCompSingleLocalPort {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(c.Contents[:2]), nil\n}\n\n// LocalPortRange returns LocalPortRange in two uint16(low, high) if the type of\n// component matches.\nfunc (c *TFTPFComponent) LocalPortRange() (uint16, uint16, error) {\n\tif c.Type != PFCompLocalPortRange {\n\t\treturn 0, 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 4 {\n\t\treturn 0, 0, io.ErrUnexpectedEOF\n\t}\n\n\tlow := binary.BigEndian.Uint16(c.Contents[0:2])\n\thigh := binary.BigEndian.Uint16(c.Contents[2:4])\n\treturn low, high, nil\n}\n\n// SingleRemotePort returns SingleRemotePort in uint16 if the type of component matches.\nfunc (c *TFTPFComponent) SingleRemotePort() (uint16, error) {\n\tif c.Type != PFCompSingleRemotePort {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(c.Contents[:2]), nil\n}\n\n// RemotePortRange returns RemotePortRange in two uint16(low, high) if the type of\n// component matches.\nfunc (c *TFTPFComponent) RemotePortRange() (uint16, uint16, error) {\n\tif c.Type != PFCompRemotePortRange {\n\t\treturn 0, 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 4 {\n\t\treturn 0, 0, io.ErrUnexpectedEOF\n\t}\n\n\tlow := binary.BigEndian.Uint16(c.Contents[0:2])\n\thigh := binary.BigEndian.Uint16(c.Contents[2:4])\n\treturn low, high, nil\n}\n\n// SecurityParameterIndex returns SecurityParameterIndex in uint32 if the type of\n// component matches.\nfunc (c *TFTPFComponent) SecurityParameterIndex() (uint32, error) {\n\tif c.Type != PFCompSecurityParameterIndex {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 4 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint32(c.Contents[:4]), nil\n}\n\n// TypeOfServiceTrafficClass returns TypeOfServiceTrafficClass in two uint8\n// (class, mask) if the type of component matches.\nfunc (c *TFTPFComponent) TypeOfServiceTrafficClass() (uint8, uint8, error) {\n\tif c.Type != PFCompTypeOfServiceTrafficClass {\n\t\treturn 0, 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 2 {\n\t\treturn 0, 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn c.Contents[0], c.Contents[1], nil\n}\n\n// FlowLabel returns FlowLabel in uint32 if the type of component matches.\nfunc (c *TFTPFComponent) FlowLabel() (uint32, error) {\n\tif c.Type != PFCompFlowLabel {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 3 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn utils.Uint24To32(c.Contents[:3]), nil\n}\n\n// DestinationMACAddress returns DestinationMACAddress in net.HardwareAddr if\n// the type of component matches.\nfunc (c *TFTPFComponent) DestinationMACAddress() (net.HardwareAddr, error) {\n\tif c.Type != PFCompDestinationMACAddress {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 6 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn net.HardwareAddr(c.Contents[:6]), nil\n}\n\n// SourceMACAddress returns SourceMACAddress in net.HardwareAddr if the type of\n// component matches.\nfunc (c *TFTPFComponent) SourceMACAddress() (net.HardwareAddr, error) {\n\tif c.Type != PFCompSourceMACAddress {\n\t\treturn nil, ErrInvalidType\n\t}\n\tif len(c.Contents) < 6 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\treturn net.HardwareAddr(c.Contents[:6]), nil\n}\n\n// Dot1QCTAGVID returns Dot1QCTAGVID in uint16 if the type of component matches.\nfunc (c *TFTPFComponent) Dot1QCTAGVID() (uint16, error) {\n\tif c.Type != PFCompDot1QCTAGVID {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(c.Contents[:2]), nil\n}\n\n// Dot1QSTAGVID returns Dot1QSTAGVID in uint16 if the type of component matches.\nfunc (c *TFTPFComponent) Dot1QSTAGVID() (uint16, error) {\n\tif c.Type != PFCompDot1QSTAGVID {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(c.Contents[:2]), nil\n}\n\n// Dot1QCTAGPCPDEI returns Dot1QCTAGPCPDEI in uint8 if the type of component matches.\nfunc (c *TFTPFComponent) Dot1QCTAGPCPDEI() (uint8, error) {\n\tif c.Type != PFCompDot1QCTAGPCPDEI {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn c.Contents[0], nil\n}\n\n// Dot1QSTAGPCPDEI returns Dot1QSTAGPCPDEI in uint8 if the type of component matches.\nfunc (c *TFTPFComponent) Dot1QSTAGPCPDEI() (uint8, error) {\n\tif c.Type != PFCompDot1QSTAGPCPDEI {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn c.Contents[0], nil\n}\n\n// Ethertype returns Ethertype in uint16 if the type of component matches.\nfunc (c *TFTPFComponent) Ethertype() (uint16, error) {\n\tif c.Type != PFCompEthertype {\n\t\treturn 0, ErrInvalidType\n\t}\n\tif len(c.Contents) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn binary.BigEndian.Uint16(c.Contents[:2]), nil\n}\n\n// Marshal serializes TFTPFComponent.\nfunc (c *TFTPFComponent) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes TFTPFComponent into b.\nfunc (c *TFTPFComponent) MarshalTo(b []byte) error {\n\tif len(b) < 1+len(c.Contents) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = c.Type\n\tcopy(b[1:1+len(c.Contents)], c.Contents)\n\n\treturn nil\n}\n\n// ParseTFTPFComponent decodes TFTPFComponent.\nfunc ParseTFTPFComponent(b []byte) (*TFTPFComponent, error) {\n\tc := &TFTPFComponent{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n\n// ParseMultiTFTPFComponent decodes TFTPFComponent.\nfunc ParseMultiTFTPFComponent(b []byte) ([]*TFTPFComponent, error) {\n\tvar comps []*TFTPFComponent\n\tfor {\n\t\tif len(b) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\ti, err := ParseTFTPFComponent(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcomps = append(comps, i)\n\t\tb = b[i.MarshalLen():]\n\t}\n\treturn comps, nil\n}\n\n// UnmarshalBinary decodes given bytes into TFTPFComponent.\nfunc (c *TFTPFComponent) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tc.Type = b[0]\n\n\tn := 0\n\tswitch c.Type {\n\tcase PFCompIPv4RemoteAddress, PFCompIPv4LocalAddress:\n\t\tn = 8\n\tcase PFCompIPv6RemoteAddress:\n\t\tn = 32\n\tcase PFCompIPv6RemoteAddressPrefixLength, PFCompIPv6LocalAddressPrefixLength:\n\t\tn = 17\n\tcase PFCompProtocolIdentifierNextHeader:\n\t\tn = 1\n\tcase PFCompSingleLocalPort, PFCompSingleRemotePort:\n\t\tn = 2\n\tcase PFCompLocalPortRange, PFCompRemotePortRange:\n\t\tn = 4\n\tcase PFCompSecurityParameterIndex:\n\t\tn = 4\n\tcase PFCompTypeOfServiceTrafficClass:\n\t\tn = 2\n\tcase PFCompFlowLabel:\n\t\tn = 3\n\tcase PFCompDestinationMACAddress, PFCompSourceMACAddress:\n\t\tn = 6\n\tcase PFCompDot1QCTAGVID, PFCompDot1QSTAGVID:\n\t\tn = 2\n\tcase PFCompDot1QCTAGPCPDEI, PFCompDot1QSTAGPCPDEI:\n\t\tn = 1\n\tcase PFCompEthertype:\n\t\tn = 2\n\t}\n\n\tif l < 1+n {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tc.Contents = b[1 : 1+n]\n\treturn nil\n}\n\n// MarshalLen returns the serial length of TFTPFComponent in int.\nfunc (c *TFTPFComponent) MarshalLen() int {\n\treturn 1 + len(c.Contents)\n}\n\n// TFT Parameter Identifier definitions.\nconst (\n\tTFTParamIDAuthorizationToken      uint8 = 1\n\tTFTParamIDFlowIdentifier          uint8 = 2\n\tTFTParamIDPacketFileterIdentifier uint8 = 3\n)\n\n// TFTParameter represents a Parameter in TFT.\ntype TFTParameter struct {\n\tIdentifier uint8\n\tLength     uint8\n\tContents   []byte\n}\n\n// NewTFTParameter creates a new TFTParameter.\nfunc NewTFTParameter(id uint8, contents []byte) *TFTParameter {\n\treturn &TFTParameter{\n\t\tIdentifier: id,\n\t\tLength:     uint8(len(contents)),\n\t\tContents:   contents,\n\t}\n}\n\n// Marshal serializes TFTParameter.\nfunc (p *TFTParameter) Marshal() ([]byte, error) {\n\tb := make([]byte, p.MarshalLen())\n\tif err := p.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes TFTParameter into b.\nfunc (p *TFTParameter) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = p.Identifier\n\tb[1] = p.Length\n\toffset := 2\n\n\tif l < offset+len(p.Contents) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[offset:offset+len(p.Contents)], p.Contents)\n\n\treturn nil\n}\n\n// ParseTFTParameter decodes TFTParameter.\nfunc ParseTFTParameter(b []byte) (*TFTParameter, error) {\n\tp := &TFTParameter{}\n\tif err := p.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn p, nil\n}\n\n// ParseMultiTFTParameters decodes TFTParameter.\nfunc ParseMultiTFTParameters(b []byte) ([]*TFTParameter, error) {\n\tvar params []*TFTParameter\n\tfor {\n\t\tif len(b) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\ti, err := ParseTFTParameter(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams = append(params, i)\n\t\tb = b[i.MarshalLen():]\n\t}\n\treturn params, nil\n}\n\n// UnmarshalBinary decodes given bytes into TFTParameter.\nfunc (p *TFTParameter) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tp.Identifier = b[0]\n\tp.Length = b[1]\n\tif l < 2+int(p.Length) {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tp.Contents = b[2 : 2+int(p.Length)]\n\n\treturn nil\n}\n\n// SetLength sets the length in TFTParameter.\nfunc (p *TFTParameter) SetLength() {\n\tp.Length = uint8(len(p.Contents))\n}\n\n// MarshalLen returns the serial length of TFTParameter in int.\nfunc (p *TFTParameter) MarshalLen() int {\n\treturn 2 + len(p.Contents)\n}\n"
  },
  {
    "path": "gtpv2/ie/tft_test.go",
    "content": "package ie_test\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\nfunc TestTrafficFlowTemplate(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tserialized  []byte\n\t\tfilters     []*ie.TFTPacketFilter\n\t\tids         []uint8\n\t\tparams      []*ie.TFTParameter\n\t}{\n\t\t{\n\t\t\t\"TFTOpCreateNewTFT/NoParams\",\n\t\t\t[]byte{\n\t\t\t\t0x54, 0x00, 0x9d, 0x00, 0x24, 0x01, 0x00, 0x57, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff,\n\t\t\t\t0x00, 0x11, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,\n\t\t\t\t0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x01, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x23, 0x20, 0x01,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x12,\n\t\t\t\t0x00, 0x12, 0x30, 0x01, 0x40, 0x08, 0x68, 0x50, 0x08, 0x4b, 0x41, 0x08, 0x4b, 0x08, 0x68, 0x51,\n\t\t\t\t0x08, 0x68, 0x08, 0x4b, 0x23, 0x00, 0x1a, 0x60, 0xde, 0xad, 0xbe, 0xef, 0x70, 0x01, 0x02, 0x80,\n\t\t\t\t0x01, 0x11, 0x11, 0x81, 0x12, 0x34, 0x56, 0x78, 0x90, 0x01, 0x82, 0x12, 0x34, 0x56, 0x78, 0x90,\n\t\t\t\t0x02, 0x34, 0x00, 0x0d, 0x83, 0x01, 0x11, 0x84, 0x02, 0x22, 0x85, 0x03, 0x86, 0x05, 0x87, 0x08,\n\t\t\t\t0x00,\n\t\t\t},\n\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv4LocalAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), net.CIDRMask(64, 128),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6LocalAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFDownlinkOnly, 2, 0,\n\t\t\t\t\tie.NewTFTPFComponentProtocolIdentifierNextHeader(1),\n\t\t\t\t\tie.NewTFTPFComponentSingleLocalPort(2152),\n\t\t\t\t\tie.NewTFTPFComponentSingleRemotePort(2123),\n\t\t\t\t\tie.NewTFTPFComponentLocalPortRange(2123, 2152),\n\t\t\t\t\tie.NewTFTPFComponentRemotePortRange(2152, 2123),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFUplinkOnly, 3, 0,\n\t\t\t\t\tie.NewTFTPFComponentSecurityParameterIndex(0xdeadbeef),\n\t\t\t\t\tie.NewTFTPFComponentTypeOfServiceTrafficClass(1, 2),\n\t\t\t\t\tie.NewTFTPFComponentFlowLabel(0x00011111),\n\t\t\t\t\tie.NewTFTPFComponentDestinationMACAddress(mac1),\n\t\t\t\t\tie.NewTFTPFComponentSourceMACAddress(mac2),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFBidirectional, 4, 0,\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGVID(0x0111),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGVID(0x0222),\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGPCPDEI(3),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGPCPDEI(5),\n\t\t\t\t\tie.NewTFTPFComponentEthertype(0x0800),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnil,\n\t\t\tnil,\n\t\t}, {\n\t\t\t\"TFTOpCreateNewTFT/WithParams\",\n\t\t\t[]byte{\n\t\t\t\t0x54, 0x00, 0xaf, 0x00, 0x34, 0x01, 0x00, 0x57, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff,\n\t\t\t\t0x00, 0x11, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,\n\t\t\t\t0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x01, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x23, 0x20, 0x01,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x12,\n\t\t\t\t0x00, 0x12, 0x30, 0x01, 0x40, 0x08, 0x68, 0x50, 0x08, 0x4b, 0x41, 0x08, 0x4b, 0x08, 0x68, 0x51,\n\t\t\t\t0x08, 0x68, 0x08, 0x4b, 0x23, 0x00, 0x1a, 0x60, 0xde, 0xad, 0xbe, 0xef, 0x70, 0x01, 0x02, 0x80,\n\t\t\t\t0x01, 0x11, 0x11, 0x81, 0x12, 0x34, 0x56, 0x78, 0x90, 0x01, 0x82, 0x12, 0x34, 0x56, 0x78, 0x90,\n\t\t\t\t0x02, 0x34, 0x00, 0x0d, 0x83, 0x01, 0x11, 0x84, 0x02, 0x22, 0x85, 0x03, 0x86, 0x05, 0x87, 0x08,\n\t\t\t\t0x00, 0x01, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x02, 0x04, 0x11, 0x11, 0x22, 0x22, 0x03, 0x04, 0x01,\n\t\t\t\t0x02, 0x03, 0x04,\n\t\t\t},\n\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv4LocalAddress(\n\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddress(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), net.CIDRMask(64, 128),\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t\tie.NewTFTPFComponentIPv6LocalAddressPrefixLength(\n\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFDownlinkOnly, 2, 0,\n\t\t\t\t\tie.NewTFTPFComponentProtocolIdentifierNextHeader(1),\n\t\t\t\t\tie.NewTFTPFComponentSingleLocalPort(2152),\n\t\t\t\t\tie.NewTFTPFComponentSingleRemotePort(2123),\n\t\t\t\t\tie.NewTFTPFComponentLocalPortRange(2123, 2152),\n\t\t\t\t\tie.NewTFTPFComponentRemotePortRange(2152, 2123),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFUplinkOnly, 3, 0,\n\t\t\t\t\tie.NewTFTPFComponentSecurityParameterIndex(0xdeadbeef),\n\t\t\t\t\tie.NewTFTPFComponentTypeOfServiceTrafficClass(1, 2),\n\t\t\t\t\tie.NewTFTPFComponentFlowLabel(0x00011111),\n\t\t\t\t\tie.NewTFTPFComponentDestinationMACAddress(mac1),\n\t\t\t\t\tie.NewTFTPFComponentSourceMACAddress(mac2),\n\t\t\t\t),\n\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\tie.TFTPFBidirectional, 4, 0,\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGVID(0x0111),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGVID(0x0222),\n\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGPCPDEI(3),\n\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGPCPDEI(5),\n\t\t\t\t\tie.NewTFTPFComponentEthertype(0x0800),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnil,\n\t\t\t[]*ie.TFTParameter{\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t\t},\n\t\t}, {\n\t\t\t\"TFTOpDeleteExistingTFT/NoParams\",\n\t\t\t[]byte{0x54, 0x00, 0x01, 0x00, 0x40},\n\t\t\tnil,\n\t\t\tnil,\n\t\t\tnil,\n\t\t}, {\n\t\t\t\"TFTOpDeleteExistingTFT/WithParams\",\n\t\t\t[]byte{\n\t\t\t\t0x54, 0x00, 0x13, 0x00, 0x50,\n\t\t\t\t0x01, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0x02, 0x04, 0x11, 0x11, 0x22, 0x22,\n\t\t\t\t0x03, 0x04, 0x01, 0x02, 0x03, 0x04,\n\t\t\t},\n\t\t\tnil,\n\t\t\tnil,\n\t\t\t[]*ie.TFTParameter{\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t\t},\n\t\t}, {\n\t\t\t\"TFTOpDeletePacketFilters/NoParams\",\n\t\t\t[]byte{0x54, 0x00, 0x05, 0x00, 0xa4, 0x01, 0x02, 0x03, 0x04},\n\t\t\tnil,\n\t\t\t[]uint8{1, 2, 3, 4},\n\t\t\tnil,\n\t\t}, {\n\t\t\t\"TFTOpDeletePacketFilters/WithParams\",\n\t\t\t[]byte{\n\t\t\t\t0x54, 0x00, 0x17, 0x00, 0xb4,\n\t\t\t\t0x01, 0x02, 0x03, 0x04,\n\t\t\t\t0x01, 0x04, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t0x02, 0x04, 0x11, 0x11, 0x22, 0x22,\n\t\t\t\t0x03, 0x04, 0x01, 0x02, 0x03, 0x04,\n\t\t\t},\n\t\t\tnil,\n\t\t\t[]uint8{1, 2, 3, 4},\n\t\t\t[]*ie.TFTParameter{\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.description, func(t *testing.T) {\n\t\t\ti, err := ie.Parse(c.serialized)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tf, err := i.TrafficFlowTemplate()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(f.PacketFilters, c.filters); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(f.PacketFilterIdentifiers, c.ids); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(f.Parameters, c.params); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "gtpv2/ie/throttling.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"time\"\n)\n\n// NewThrottling creates a new Timer IE.\nfunc NewThrottling(delay time.Duration, factor uint8) *IE {\n\tv := NewThrottlingFields(delay, factor)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(Throttling, 0x00, b)\n}\n\n// Throttling returns Throttling in time.Duration if the type of IE matches.\nfunc (i *IE) Throttling() (*ThrottlingFields, error) {\n\tswitch i.Type {\n\tcase Throttling:\n\t\treturn ParseThrottlingFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// ThrottlingFields is a set of fields in Throttling IE.\ntype ThrottlingFields struct {\n\tDelayUnit  uint8\n\tDelayValue time.Duration\n\tFactor     uint8\n}\n\n// NewThrottlingFields creates a new ThrottlingFields.\nfunc NewThrottlingFields(delay time.Duration, factor uint8) *ThrottlingFields {\n\t// 8.85 Throttling\n\t// Bits 5 to 1 represent the binary coded timer value.\n\t// Bits 6 to 8 defines the timer value unit as follows:\n\t// Bits\n\t// 8 7 6\n\t// 0 0 0 value is incremented in multiples of 2 seconds\n\t// 0 0 1 value is incremented in multiples of 1 minute\n\t// 0 1 0 value is incremented in multiples of 10 minutes\n\t// 0 1 1 value is incremented in multiples of 1 hour\n\t// 1 0 0 value is incremented in multiples of 10 hours\n\t// 1 1 1 value indicates that the timer is infinite\n\t//\n\t// Other values shall be interpreted as multiples of 1 minute in this version of the protocol.\n\t// Timer unit and Timer value both set to all \"zeros\" shall be interpreted as an indication that the timer is stopped.\n\n\tvar unit uint8\n\tswitch {\n\tcase delay%(10*time.Hour) == 0:\n\t\tunit = 0x04\n\tcase delay%(1*time.Hour) == 0:\n\t\tunit = 0x03\n\tcase delay%(10*time.Minute) == 0:\n\t\tunit = 0x02\n\tcase delay%(1*time.Minute) == 0:\n\t\tunit = 0x01\n\tcase delay%(2*time.Second) == 0:\n\t\tunit = 0x00\n\tdefault:\n\t\tunit = 0xe0\n\t}\n\n\treturn &ThrottlingFields{\n\t\tDelayUnit:  unit,\n\t\tDelayValue: delay,\n\t\tFactor:     factor,\n\t}\n}\n\n// Marshal serializes ThrottlingFields.\nfunc (f *ThrottlingFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes ThrottlingFields.\nfunc (f *ThrottlingFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tvar value uint8\n\tswitch f.DelayUnit {\n\tcase 0x04:\n\t\tvalue = uint8(f.DelayValue / (10 * time.Hour))\n\tcase 0x03:\n\t\tvalue = uint8(f.DelayValue / time.Hour)\n\tcase 0x02:\n\t\tvalue = uint8(f.DelayValue / (10 * time.Minute))\n\tcase 0x01:\n\t\tvalue = uint8(f.DelayValue / time.Minute)\n\tcase 0x00:\n\t\tvalue = uint8(f.DelayValue / (2 * time.Second))\n\tdefault:\n\t\tvalue = 0\n\t}\n\n\tb[0] = ((f.DelayUnit << 5) & 0xe0) | (value & 0x1f)\n\tb[1] = f.Factor\n\n\treturn nil\n}\n\n// ParseThrottlingFields decodes ThrottlingFields.\nfunc ParseThrottlingFields(b []byte) (*ThrottlingFields, error) {\n\tf := &ThrottlingFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into ThrottlingFields.\nfunc (f *ThrottlingFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 2 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.DelayUnit = (b[0] & 0xe0) >> 5\n\n\tswitch f.DelayUnit {\n\tcase 0x04:\n\t\tf.DelayValue = time.Duration(b[0]&0x1f) * (10 * time.Hour)\n\tcase 0x03:\n\t\tf.DelayValue = time.Duration(b[0]&0x1f) * time.Hour\n\tcase 0x02:\n\t\tf.DelayValue = time.Duration(b[0]&0x1f) * (10 * time.Minute)\n\tcase 0x01:\n\t\tf.DelayValue = time.Duration(b[0]&0x1f) * time.Minute\n\tcase 0x00:\n\t\tf.DelayValue = time.Duration(b[0]&0x1f) * (2 * time.Second)\n\tdefault:\n\t\tf.DelayValue = 0\n\t}\n\n\tf.Factor = b[1]\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of ThrottlingFields in int.\nfunc (f *ThrottlingFields) MarshalLen() int {\n\treturn 2\n}\n"
  },
  {
    "path": "gtpv2/ie/tmsi.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\n// NewTMSI creates a new TMSI IE.\nfunc NewTMSI(tmsi uint32) *IE {\n\treturn NewUint32IE(TMSI, tmsi)\n}\n\n// TMSI returns TMSI in uint32 if the type of IE matches.\nfunc (i *IE) TMSI() (uint32, error) {\n\tswitch i.Type {\n\tcase TMSI:\n\t\treturn i.ValueAsUint32()\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustTMSI returns TMSI in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTMSI() uint32 {\n\tv, _ := i.TMSI()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/trace-reference.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewTraceReference creates a new TraceReference IE.\nfunc NewTraceReference(mcc, mnc string, traceID uint32) *IE {\n\tv := NewTraceReferenceFields(mcc, mnc, traceID)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(TraceReference, 0x00, b)\n}\n\n// TraceReferenceFields is a set of fields in TraceReference IE.\ntype TraceReferenceFields struct {\n\tMCC, MNC string\n\tTraceID  uint32 // 24-bit\n}\n\n// NewTraceReferenceFields creates a new TraceReferenceFields.\nfunc NewTraceReferenceFields(mcc, mnc string, traceID uint32) *TraceReferenceFields {\n\treturn &TraceReferenceFields{\n\t\tMCC:     mcc,\n\t\tMNC:     mnc,\n\t\tTraceID: traceID,\n\t}\n}\n\n// Marshal serializes TraceReferenceFields.\nfunc (f *TraceReferenceFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes TraceReferenceFields.\nfunc (f *TraceReferenceFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tplmn, err := utils.EncodePLMN(f.MCC, f.MNC)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcopy(b[0:3], plmn)\n\n\tif l < 6 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tcopy(b[3:6], utils.Uint32To24(f.TraceID))\n\n\treturn nil\n}\n\n// ParseTraceReferenceFields decodes TraceReferenceFields.\nfunc ParseTraceReferenceFields(b []byte) (*TraceReferenceFields, error) {\n\tf := &TraceReferenceFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into TraceReferenceFields.\nfunc (f *TraceReferenceFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tvar err error\n\tf.MCC, f.MNC, err = utils.DecodePLMN(b[0:3])\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif l < 6 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tf.TraceID = utils.Uint24To32(b[3:6])\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of TraceReferenceFields in int.\nfunc (f *TraceReferenceFields) MarshalLen() int {\n\treturn 6\n}\n\n// TraceID returns TraceID in uint32 if the type of IE matches.\nfunc (i *IE) TraceID() (uint32, error) {\n\tswitch i.Type {\n\tcase TraceReference, TraceInformation:\n\t\tif len(i.Payload) < 6 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn utils.Uint24To32(i.Payload[3:6]), nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustTraceID returns TraceID in uint32, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTraceID() uint32 {\n\tv, _ := i.TraceID()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/uci.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\n// NewUserCSGInformation creates a new UserCSGInformation IE.\nfunc NewUserCSGInformation(mcc, mnc string, csgID uint32, mode, lcsg, cmi uint8) *IE {\n\tv := NewUserCSGInformationFields(mcc, mnc, csgID, mode, lcsg, cmi)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(UserCSGInformation, 0x00, b)\n}\n\n// UserCSGInformation returns UserCSGInformation in UserCSGInformationFields type if the type of IE matches.\nfunc (i *IE) UserCSGInformation() (*UserCSGInformationFields, error) {\n\tswitch i.Type {\n\tcase UserCSGInformation:\n\t\treturn ParseUserCSGInformationFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// UserCSGInformationFields is a set of fields in UserCSGInformation IE.\ntype UserCSGInformationFields struct {\n\tMCC, MNC   string\n\tCSGID      uint32 // 27-bit\n\tAccessMode uint8  // 7-8th bit, in the same octet as Flags\n\tFlags      uint8  // 1-2th bit, in the same octet as AccessMode\n}\n\n// NewUserCSGInformationFields creates a new UserCSGInformationFields.\nfunc NewUserCSGInformationFields(mcc, mnc string, csgID uint32, mode, lcsg, cmi uint8) *UserCSGInformationFields {\n\treturn &UserCSGInformationFields{\n\t\tMCC:        mcc,\n\t\tMNC:        mnc,\n\t\tCSGID:      csgID,\n\t\tAccessMode: mode,\n\t\tFlags:      ((lcsg << 1) & 0x02) | (cmi & 0x01),\n\t}\n}\n\n// Marshal serializes UserCSGInformationFields.\nfunc (f *UserCSGInformationFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes UserCSGInformationFields.\nfunc (f *UserCSGInformationFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tplmn, err := utils.EncodePLMN(f.MCC, f.MNC)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcopy(b[0:3], plmn)\n\n\tif l < 8 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tbinary.BigEndian.PutUint32(b[3:7], f.CSGID&0x7ffffff)\n\tb[7] = ((f.AccessMode & 0x03) << 6) | f.Flags\n\n\treturn nil\n}\n\n// ParseUserCSGInformationFields decodes UserCSGInformationFields.\nfunc ParseUserCSGInformationFields(b []byte) (*UserCSGInformationFields, error) {\n\tf := &UserCSGInformationFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into UserCSGInformationFields.\nfunc (f *UserCSGInformationFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 3 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tvar err error\n\tf.MCC, f.MNC, err = utils.DecodePLMN(b[0:3])\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif l <= 7 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tf.CSGID = binary.BigEndian.Uint32(b[3:7]) & 0x7ffffff\n\tf.AccessMode = b[7] >> 6\n\tf.Flags = b[7] & 0x03\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of UserCSGInformationFields in int.\nfunc (f *UserCSGInformationFields) MarshalLen() int {\n\treturn 8\n}\n\n// AccessMode returns AccessMode in uint8 if the type of IE matches.\nfunc (i *IE) AccessMode() (uint8, error) {\n\tswitch i.Type {\n\tcase UserCSGInformation:\n\t\tif len(i.Payload) < 8 {\n\t\t\treturn 0, io.ErrUnexpectedEOF\n\t\t}\n\t\treturn i.Payload[7] >> 6, nil\n\tdefault:\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustAccessMode returns AccessMode in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustAccessMode() uint8 {\n\tv, _ := i.AccessMode()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/ue-timezone.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"io\"\n\t\"math\"\n\t\"time\"\n)\n\n// NewUETimeZone creates a new UETimeZone IE.\nfunc NewUETimeZone(tz time.Duration, daylightSaving uint8) *IE {\n\ti := New(UETimeZone, 0x00, make([]byte, 2))\n\tmin := tz.Minutes() / 15\n\tabsMin := int(math.Abs(min))\n\thex := byte(((absMin % 10) << 4) | (absMin / 10))\n\tif min < 0 {\n\t\thex |= 0x08\n\t}\n\ti.Payload[0] = hex\n\ti.Payload[1] = daylightSaving & 0x03\n\n\treturn i\n}\n\n// TimeZone returns TimeZone in time.Duration if the type of IE matches.\nfunc (i *IE) TimeZone() (time.Duration, error) {\n\tif i.Type != UETimeZone {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 1 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\tunsigned := i.Payload[0] & 0xf7\n\tdec := int((unsigned >> 4) + (unsigned&0x0f)*10)\n\tif (i.Payload[0]&0x08)>>3 == 1 {\n\t\tdec *= -1\n\t}\n\n\treturn time.Duration(dec*15) * time.Minute, nil\n}\n\n// MustTimeZone returns TimeZone in time.Duration, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTimeZone() time.Duration {\n\tv, _ := i.TimeZone()\n\treturn v\n}\n\n// DaylightSaving returns DaylightSaving in uint8 if the type of IE matches.\nfunc (i *IE) DaylightSaving() (uint8, error) {\n\tif i.Type != UETimeZone {\n\t\treturn 0, &InvalidTypeError{Type: i.Type}\n\t}\n\tif len(i.Payload) < 2 {\n\t\treturn 0, io.ErrUnexpectedEOF\n\t}\n\n\treturn i.Payload[1], nil\n}\n\n// MustDaylightSaving returns DaylightSaving in uint8, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustDaylightSaving() uint8 {\n\tv, _ := i.DaylightSaving()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/uli-timestamp.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\t\"time\"\n)\n\n// NewULITimestamp creates a new ULITimestamp IE.\nfunc NewULITimestamp(ts time.Time) *IE {\n\tu64sec := uint64(ts.Sub(time.Date(1900, time.January, 1, 0, 0, 0, 0, time.UTC))) / 1000000000\n\treturn NewUint32IE(ULITimestamp, uint32(u64sec))\n}\n\n// Timestamp returns Timestamp in time.Time if the type of IE matches.\nfunc (i *IE) Timestamp() (time.Time, error) {\n\tif len(i.Payload) < 4 {\n\t\treturn time.Time{}, io.ErrUnexpectedEOF\n\t}\n\n\tswitch i.Type {\n\tcase ULITimestamp, TWANIdentifierTimestamp:\n\t\treturn time.Unix(int64(binary.BigEndian.Uint32(i.Payload)-2208988800), 0), nil\n\tdefault:\n\t\treturn time.Time{}, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// MustTimestamp returns Timestamp in time.Time, ignoring errors.\n// This should only be used if it is assured to have the value.\nfunc (i *IE) MustTimestamp() time.Time {\n\tv, _ := i.Timestamp()\n\treturn v\n}\n"
  },
  {
    "path": "gtpv2/ie/uli.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\nconst (\n\tcgilen    int = 7\n\tsailen    int = 7\n\trailen    int = 7\n\ttailen    int = 5\n\tecgilen   int = 7\n\tlailen    int = 5\n\tmenbilen  int = 6\n\temenbilen int = 6\n)\n\nconst (\n\tuliFlagCGI    uint8 = 0x01\n\tuliFlagSAI    uint8 = 0x02\n\tuliFlagRAI    uint8 = 0x04\n\tuliFlagTAI    uint8 = 0x08\n\tuliFlagECGI   uint8 = 0x10\n\tuliFlagLAI    uint8 = 0x20\n\tuliFlagMENBI  uint8 = 0x40\n\tuliFlagEMENBI uint8 = 0x80\n)\n\ntype PLMN struct {\n\tMCC string\n\tMNC string\n}\n\n// MCCFromPLMN gets MCC from PLMN.\nfunc (plmn *PLMN) MCCFromPLMN() string {\n\treturn plmn.MCC\n}\n\n// MNCFromPLMN gets MNC from PLMN.\nfunc (plmn *PLMN) MNCFromPLMN() string {\n\treturn plmn.MNC\n}\n\n// CGI represents a CGI, which is defined to be used as a field of UserLocationInformation IE.\ntype CGI struct {\n\t*PLMN\n\tLAC uint16\n\tCI  uint16\n}\n\n// NewCGI creates a new CGI.\nfunc NewCGI(mcc, mnc string, lac, ci uint16) *CGI {\n\treturn &CGI{\n\t\tPLMN: &PLMN{MCC: mcc, MNC: mnc},\n\t\tLAC:  lac,\n\t\tCI:   ci,\n\t}\n}\n\n// HasCGI checks if UserLocationInformationFields has CGI.\nfunc (f *UserLocationInformationFields) HasCGI() bool {\n\treturn f.Flags&uliFlagCGI != 0\n}\n\n// SAI represents a SAI, which is defined to be used as a field of UserLocationInformation IE.\ntype SAI struct {\n\t*PLMN\n\tLAC uint16\n\tSAC uint16\n}\n\n// NewSAI creates a new SAI.\nfunc NewSAI(mcc, mnc string, lac, sac uint16) *SAI {\n\treturn &SAI{\n\t\tPLMN: &PLMN{MCC: mcc, MNC: mnc},\n\t\tLAC:  lac,\n\t\tSAC:  sac,\n\t}\n}\n\n// HasSAI checks if UserLocationInformationFields has SAI.\nfunc (f *UserLocationInformationFields) HasSAI() bool {\n\treturn f.Flags&uliFlagSAI != 0\n}\n\n// RAI represents a RAI, which is defined to be used as a field of UserLocationInformation IE.\ntype RAI struct {\n\t*PLMN\n\tLAC uint16\n\tRAC uint16\n}\n\n// NewRAI creates a new RAI.\nfunc NewRAI(mcc, mnc string, lac, rac uint16) *RAI {\n\treturn &RAI{\n\t\tPLMN: &PLMN{MCC: mcc, MNC: mnc},\n\t\tLAC:  lac,\n\t\tRAC:  rac,\n\t}\n}\n\n// HasRAI checks if UserLocationInformationFields has RAI.\nfunc (f *UserLocationInformationFields) HasRAI() bool {\n\treturn f.Flags&uliFlagRAI != 0\n}\n\n// TAI represents a TAI, which is defined to be used as a field of UserLocationInformation IE.\ntype TAI struct {\n\t*PLMN\n\tTAC uint16\n}\n\n// NewTAI creates a new TAI.\nfunc NewTAI(mcc, mnc string, tac uint16) *TAI {\n\treturn &TAI{\n\t\tPLMN: &PLMN{MCC: mcc, MNC: mnc},\n\t\tTAC:  tac,\n\t}\n}\n\n// HasTAI checks if UserLocationInformationFields has TAI.\nfunc (f *UserLocationInformationFields) HasTAI() bool {\n\treturn f.Flags&uliFlagTAI != 0\n}\n\n// ECGI represents a ECGI, which is defined to be used as a field of UserLocationInformation IE.\ntype ECGI struct {\n\t*PLMN\n\tECI uint32\n}\n\n// NewECGI creates a new ECGI.\nfunc NewECGI(mcc, mnc string, eci uint32) *ECGI {\n\treturn &ECGI{\n\t\tPLMN: &PLMN{MCC: mcc, MNC: mnc},\n\t\tECI:  eci & 0xfffffff,\n\t}\n}\n\n// HasECGI checks if UserLocationInformationFields has ECGI.\nfunc (f *UserLocationInformationFields) HasECGI() bool {\n\treturn f.Flags&uliFlagECGI != 0\n}\n\n// LAI represents a LAI, which is defined to be used as a field of UserLocationInformation IE.\ntype LAI struct {\n\t*PLMN\n\tLAC uint16\n}\n\n// NewLAI creates a new LAI.\nfunc NewLAI(mcc, mnc string, lac uint16) *LAI {\n\treturn &LAI{\n\t\tPLMN: &PLMN{MCC: mcc, MNC: mnc},\n\t\tLAC:  lac,\n\t}\n}\n\n// HasLAI checks if UserLocationInformationFields has LAI.\nfunc (f *UserLocationInformationFields) HasLAI() bool {\n\treturn f.Flags&uliFlagLAI != 0\n}\n\n// MENBI represents a MENBI, which is defined to be used as a field of UserLocationInformation IE.\ntype MENBI struct {\n\t*PLMN\n\tMENBI uint32\n}\n\n// NewMENBI creates a new MENBI.\nfunc NewMENBI(mcc, mnc string, menbi uint32) *MENBI {\n\treturn &MENBI{\n\t\tPLMN:  &PLMN{MCC: mcc, MNC: mnc},\n\t\tMENBI: menbi,\n\t}\n}\n\n// HasMENBI checks if UserLocationInformationFields has MENBI.\nfunc (f *UserLocationInformationFields) HasMENBI() bool {\n\treturn f.Flags&uliFlagMENBI != 0\n}\n\n// EMENBI represents a EMENBI, which is defined to be used as a field of UserLocationInformation IE.\ntype EMENBI struct {\n\t*PLMN\n\tEMENBI uint32\n}\n\n// NewEMENBI creates a new EMENBI.\nfunc NewEMENBI(mcc, mnc string, menbi uint32) *EMENBI {\n\treturn &EMENBI{\n\t\tPLMN:   &PLMN{MCC: mcc, MNC: mnc},\n\t\tEMENBI: menbi,\n\t}\n}\n\n// HasEMENBI checks if UserLocationInformationFields has EMENBI.\nfunc (f *UserLocationInformationFields) HasEMENBI() bool {\n\treturn f.Flags&uliFlagEMENBI != 0\n}\n\n// NewUserLocationInformationStruct creates a new UserLocationInformation IE from\n// the structs defined in gtpv2/ie package. Give nil for unnecessary values.\nfunc NewUserLocationInformationStruct(cgi *CGI, sai *SAI, rai *RAI, tai *TAI, ecgi *ECGI, lai *LAI, menbi *MENBI, emenbi *EMENBI) *IE {\n\tv := NewUserLocationInformationFields(cgi, sai, rai, tai, ecgi, lai, menbi, emenbi)\n\tb, err := v.Marshal()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn New(UserLocationInformation, 0x00, b)\n}\n\n// UserLocationInformation returns UserLocationInformation in UserLocationInformationFields type\n// if the type of IE matches.\nfunc (i *IE) UserLocationInformation() (*UserLocationInformationFields, error) {\n\tswitch i.Type {\n\tcase UserLocationInformation:\n\t\treturn ParseUserLocationInformationFields(i.Payload)\n\tdefault:\n\t\treturn nil, &InvalidTypeError{Type: i.Type}\n\t}\n}\n\n// UserLocationInformationFields is a set of fields in UserLocationInformation IE.\n//\n// The contained fields are of type struct, as they are too complex to handle with\n// existing (standard) types in Go.\ntype UserLocationInformationFields struct {\n\tFlags uint8\n\t*CGI\n\t*SAI\n\t*RAI\n\t*TAI\n\t*ECGI\n\t*LAI\n\t*MENBI\n\t*EMENBI\n}\n\n// NewUserLocationInformationFields creates a new NewUserLocationInformationFields.\nfunc NewUserLocationInformationFields(cgi *CGI, sai *SAI, rai *RAI, tai *TAI, ecgi *ECGI, lai *LAI, menbi *MENBI, emenbi *EMENBI) *UserLocationInformationFields {\n\tf := &UserLocationInformationFields{}\n\n\tif cgi != nil {\n\t\tf.Flags |= uliFlagCGI\n\t\tf.CGI = cgi\n\t}\n\tif sai != nil {\n\t\tf.Flags |= uliFlagSAI\n\t\tf.SAI = sai\n\t}\n\tif rai != nil {\n\t\tf.Flags |= uliFlagRAI\n\t\tf.RAI = rai\n\t}\n\tif tai != nil {\n\t\tf.Flags |= uliFlagTAI\n\t\tf.TAI = tai\n\t}\n\tif ecgi != nil {\n\t\tf.Flags |= uliFlagECGI\n\t\tf.ECGI = ecgi\n\t}\n\tif lai != nil {\n\t\tf.Flags |= uliFlagLAI\n\t\tf.LAI = lai\n\t}\n\tif menbi != nil {\n\t\tf.Flags |= uliFlagMENBI\n\t\tf.MENBI = menbi\n\t}\n\tif emenbi != nil {\n\t\tf.Flags |= uliFlagEMENBI\n\t\tf.EMENBI = emenbi\n\t}\n\n\treturn f\n}\n\n// Marshal serializes UserLocationInformationFields.\nfunc (f *UserLocationInformationFields) Marshal() ([]byte, error) {\n\tb := make([]byte, f.MarshalLen())\n\tif err := f.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo serializes UserLocationInformationFields.\nfunc (f *UserLocationInformationFields) MarshalTo(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\n\tb[0] = f.Flags\n\toffset := 1\n\n\tif has1stBit(f.Flags) { // CGI\n\t\tif l < offset+cgilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.CGI.MCC, f.CGI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(b[offset+3:offset+5], f.CGI.LAC)\n\t\tbinary.BigEndian.PutUint16(b[offset+5:offset+7], f.CGI.CI)\n\t\toffset += cgilen\n\t}\n\tif has2ndBit(f.Flags) { // SAI\n\t\tif l < offset+sailen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.SAI.MCC, f.SAI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(b[offset+3:offset+5], f.SAI.LAC)\n\t\tbinary.BigEndian.PutUint16(b[offset+5:offset+7], f.SAI.SAC)\n\t\toffset += sailen\n\t}\n\tif has3rdBit(f.Flags) { // RAI\n\t\tif l < offset+railen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.RAI.MCC, f.RAI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(b[offset+3:offset+5], f.RAI.LAC)\n\t\tbinary.BigEndian.PutUint16(b[offset+5:offset+7], f.RAI.RAC)\n\t\toffset += railen\n\t}\n\tif has4thBit(f.Flags) { // TAI\n\t\tif l < offset+tailen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.TAI.MCC, f.TAI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(b[offset+3:offset+5], f.TAI.TAC)\n\t\toffset += tailen\n\t}\n\tif has5thBit(f.Flags) { // ECGI\n\t\tif l < offset+ecgilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.ECGI.MCC, f.ECGI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint32(b[offset+3:offset+7], f.ECGI.ECI)\n\t\toffset += ecgilen\n\t}\n\tif has6thBit(f.Flags) { // LAI\n\t\tif l < offset+lailen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.LAI.MCC, f.LAI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(b[offset+3:offset+5], f.LAI.LAC)\n\t\toffset += lailen\n\t}\n\tif has7thBit(f.Flags) { // MENBI\n\t\tif l < offset+menbilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.MENBI.MCC, f.MENBI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tcopy(b[offset+3:offset+6], utils.Uint32To24(f.MENBI.MENBI))\n\t\toffset += menbilen\n\t}\n\tif has8thBit(f.Flags) { // EMENBI\n\t\tif l < offset+emenbilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tplmn, err := utils.EncodePLMN(f.EMENBI.MCC, f.EMENBI.MNC)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcopy(b[offset:offset+3], plmn)\n\t\tcopy(b[offset+3:offset+6], utils.Uint32To24(f.EMENBI.EMENBI))\n\t}\n\n\treturn nil\n}\n\n// ParseUserLocationInformationFields decodes UserLocationInformationFields.\nfunc ParseUserLocationInformationFields(b []byte) (*UserLocationInformationFields, error) {\n\tf := &UserLocationInformationFields{}\n\tif err := f.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn f, nil\n}\n\n// UnmarshalBinary decodes given bytes into UserLocationInformationFields.\nfunc (f *UserLocationInformationFields) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 1 {\n\t\treturn io.ErrUnexpectedEOF\n\t}\n\tf.Flags = b[0]\n\toffset := 1\n\n\tvar err error\n\tif has1stBit(f.Flags) { // CGI\n\t\tif l < offset+cgilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.CGI = &CGI{PLMN: &PLMN{}}\n\t\tf.CGI.PLMN.MCC, f.CGI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.CGI.LAC = binary.BigEndian.Uint16(b[offset+3 : offset+5])\n\t\tf.CGI.CI = binary.BigEndian.Uint16(b[offset+5 : offset+7])\n\t\toffset += cgilen\n\t}\n\tif has2ndBit(f.Flags) { // SAI\n\t\tif l < offset+sailen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.SAI = &SAI{PLMN: &PLMN{}}\n\t\tf.SAI.PLMN.MCC, f.SAI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.SAI.LAC = binary.BigEndian.Uint16(b[offset+3 : offset+5])\n\t\tf.SAI.SAC = binary.BigEndian.Uint16(b[offset+5 : offset+7])\n\t\toffset += sailen\n\t}\n\tif has3rdBit(f.Flags) { // RAI\n\t\tif l < offset+railen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.RAI = &RAI{PLMN: &PLMN{}}\n\t\tf.RAI.PLMN.MCC, f.RAI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.RAI.LAC = binary.BigEndian.Uint16(b[offset+3 : offset+5])\n\t\tf.RAI.RAC = binary.BigEndian.Uint16(b[offset+5 : offset+7])\n\t\toffset += railen\n\t}\n\tif has4thBit(f.Flags) { // TAI\n\t\tif l < offset+tailen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.TAI = &TAI{PLMN: &PLMN{}}\n\t\tf.TAI.PLMN.MCC, f.TAI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.TAI.TAC = binary.BigEndian.Uint16(b[offset+3 : offset+5])\n\t\toffset += tailen\n\t}\n\tif has5thBit(f.Flags) { // ECGI\n\t\tif l < offset+ecgilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.ECGI = &ECGI{PLMN: &PLMN{}}\n\t\tf.ECGI.PLMN.MCC, f.ECGI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.ECGI.ECI = binary.BigEndian.Uint32(b[offset+3 : offset+7])\n\t\toffset += ecgilen\n\t}\n\tif has6thBit(f.Flags) { // LAI\n\t\tif l < offset+lailen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.LAI = &LAI{PLMN: &PLMN{}}\n\t\tf.LAI.PLMN.MCC, f.LAI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.LAI.LAC = binary.BigEndian.Uint16(b[offset+3 : offset+5])\n\t\toffset += lailen\n\t}\n\tif has7thBit(f.Flags) { // MENBI\n\t\tif l < offset+menbilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.MENBI = &MENBI{PLMN: &PLMN{}}\n\t\tf.MENBI.PLMN.MCC, f.MENBI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.MENBI.MENBI = utils.Uint24To32(b[offset+3 : offset+6])\n\t\toffset += menbilen\n\t}\n\tif has8thBit(f.Flags) { // EMENBI\n\t\tif l < offset+emenbilen {\n\t\t\treturn io.ErrUnexpectedEOF\n\t\t}\n\n\t\tf.EMENBI = &EMENBI{PLMN: &PLMN{}}\n\t\tf.EMENBI.PLMN.MCC, f.EMENBI.PLMN.MNC, err = utils.DecodePLMN(b[offset : offset+3])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.EMENBI.EMENBI = utils.Uint24To32(b[offset+3 : offset+6])\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of UserLocationInformationFields in int.\nfunc (f *UserLocationInformationFields) MarshalLen() int {\n\tl := 1\n\n\tif has1stBit(f.Flags) {\n\t\tl += cgilen\n\t}\n\tif has2ndBit(f.Flags) {\n\t\tl += sailen\n\t}\n\tif has3rdBit(f.Flags) {\n\t\tl += railen\n\t}\n\tif has4thBit(f.Flags) {\n\t\tl += tailen\n\t}\n\tif has5thBit(f.Flags) {\n\t\tl += ecgilen\n\t}\n\tif has6thBit(f.Flags) {\n\t\tl += lailen\n\t}\n\tif has7thBit(f.Flags) {\n\t\tl += menbilen\n\t}\n\tif has8thBit(f.Flags) {\n\t\tl += emenbilen\n\t}\n\n\treturn l\n}\n\n// NewUserLocationInformationLazy creates a new UserLocationInformation IE.\n//\n// The flags and corresponding fields are automatically set depending on the values given in int.\n// If a value is less than 0, the field is considered as missing.\n//\n// Deprecated: use NewUserLocationInformationStruct instead. At some point this will be removed.\nfunc NewUserLocationInformationLazy(mcc, mnc string, lac, ci, sac, rac, tac, eci, menbi, emenbi int) *IE {\n\tvar hasCGI, hasSAI, hasRAI, hasTAI, hasECGI, hasLAI, hasMENBI, hasEMENBI uint8\n\tif ci >= 0 {\n\t\thasCGI = 1\n\t}\n\tif sac >= 0 {\n\t\thasSAI = 1\n\t}\n\tif rac >= 0 {\n\t\thasRAI = 1\n\t}\n\tif tac >= 0 {\n\t\thasTAI = 1\n\t}\n\tif eci >= 0 {\n\t\thasECGI = 1\n\t}\n\tif lac >= 0 {\n\t\thasLAI = 1\n\t}\n\tif menbi >= 0 {\n\t\thasMENBI = 1\n\t}\n\tif emenbi >= 0 {\n\t\thasEMENBI = 1\n\t}\n\n\treturn NewUserLocationInformation(\n\t\thasCGI, hasSAI, hasRAI, hasTAI, hasECGI, hasLAI, hasMENBI, hasEMENBI,\n\t\tmcc, mnc, uint16(lac), uint16(ci), uint16(sac), uint16(rac), uint16(tac),\n\t\tuint32(eci), uint32(menbi), uint32(emenbi),\n\t)\n}\n\n// NewUserLocationInformation creates a new UserLocationInformation IE.\n//\n// Deprecated: use NewUserLocationInformationStruct instead. At some point this will be removed.\nfunc NewUserLocationInformation(\n\thasCGI, hasSAI, hasRAI, hasTAI, hasECGI, hasLAI, hasMENBI, hasEMENBI uint8,\n\tmcc, mnc string, lac, ci, sac, rac, tac uint16, eci, menbi, emenbi uint32,\n) *IE {\n\tflags := ((hasEMENBI & 0x01) << 7) |\n\t\t((hasMENBI & 0x01) << 6) |\n\t\t((hasLAI & 0x01) << 5) |\n\t\t((hasECGI & 0x01) << 4) |\n\t\t((hasTAI & 0x01) << 3) |\n\t\t((hasRAI & 0x01) << 2) |\n\t\t((hasSAI & 0x01) << 1) |\n\t\t(hasCGI & 0x01)\n\n\ti := New(UserLocationInformation, 0x00, make([]byte, uliPayloadLen(flags)))\n\ti.Payload[0] = flags\n\n\tplmn, err := utils.EncodePLMN(mcc, mnc)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\toffset := 1\n\tif flags&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+3:offset+5], lac)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+5:offset+7], ci)\n\t\toffset += cgilen\n\t}\n\tif flags>>1&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+3:offset+5], lac)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+5:offset+7], sac)\n\t\toffset += sailen\n\t}\n\tif flags>>2&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+3:offset+5], lac)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+5:offset+7], rac)\n\t\toffset += railen\n\t}\n\tif flags>>3&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+3:offset+5], tac)\n\t\toffset += tailen\n\t}\n\tif flags>>4&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\teci &= 0xfffff\n\t\tbinary.BigEndian.PutUint32(i.Payload[offset+3:offset+7], eci)\n\t\toffset += ecgilen\n\t}\n\tif flags>>5&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tbinary.BigEndian.PutUint16(i.Payload[offset+3:offset+5], lac)\n\t\toffset += lailen\n\t}\n\tif flags>>6&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tcopy(i.Payload[offset+3:offset+6], utils.Uint32To24(menbi))\n\t\toffset += menbilen\n\t}\n\tif flags>>7&0x01 == 1 {\n\t\tcopy(i.Payload[offset:offset+3], plmn)\n\t\tcopy(i.Payload[offset+3:offset+6], utils.Uint32To24(emenbi))\n\t}\n\treturn i\n}\n\nfunc uliPayloadLen(flags uint8) int {\n\tl := 1\n\tif flags&uliFlagCGI != 0 {\n\t\tl += cgilen\n\t}\n\tif flags&uliFlagSAI != 0 {\n\t\tl += sailen\n\t}\n\tif flags&uliFlagRAI != 0 {\n\t\tl += railen\n\t}\n\tif flags&uliFlagTAI != 0 {\n\t\tl += tailen\n\t}\n\tif flags&uliFlagECGI != 0 {\n\t\tl += ecgilen\n\t}\n\tif flags&uliFlagLAI != 0 {\n\t\tl += lailen\n\t}\n\tif flags&uliFlagMENBI != 0 {\n\t\tl += menbilen\n\t}\n\tif flags&uliFlagEMENBI != 0 {\n\t\tl += emenbilen\n\t}\n\treturn l\n}\n\n// UserLocationInfo is a getter function to parse UserLocationInformationFields\n//\n// Deprecated: use UserLocationInformation instead. At some point this will be removed.\nfunc (i *IE) UserLocationInfo() (*UserLocationInformationFields, error) {\n\tvar uli UserLocationInformationFields\n\tvar plmn PLMN\n\tl := len(i.Payload)\n\tif l == 0 {\n\t\treturn &uli, io.ErrUnexpectedEOF\n\t}\n\toffset := 1\n\tif i.Payload[0]&0x01 == 1 {\n\t\tif l < (offset + cgilen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar cgi CGI\n\t\tuli.CGI = &cgi\n\t\tuli.CGI.PLMN = &plmn\n\t\tuli.CGI.PLMN.MCC, uli.CGI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.CGI.LAC = binary.BigEndian.Uint16(i.Payload[offset+3 : offset+5])\n\t\tuli.CGI.CI = binary.BigEndian.Uint16(i.Payload[offset+5 : offset+7])\n\t\toffset += cgilen\n\t}\n\tif i.Payload[0]>>1&0x01 == 1 {\n\t\tif l < (offset + sailen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar sai SAI\n\t\tuli.SAI = &sai\n\t\tuli.SAI.PLMN = &plmn\n\t\tuli.SAI.PLMN.MCC, uli.SAI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.SAI.LAC = binary.BigEndian.Uint16(i.Payload[offset+3 : offset+5])\n\t\tuli.SAI.SAC = binary.BigEndian.Uint16(i.Payload[offset+5 : offset+7])\n\t\toffset += sailen\n\t}\n\tif i.Payload[0]>>2&0x01 == 1 {\n\t\tif l < (offset + railen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar rai RAI\n\t\tuli.RAI = &rai\n\t\tuli.RAI.PLMN = &plmn\n\t\tuli.RAI.PLMN.MCC, uli.RAI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.RAI.LAC = binary.BigEndian.Uint16(i.Payload[offset+3 : offset+5])\n\t\tuli.RAI.RAC = binary.BigEndian.Uint16(i.Payload[offset+5 : offset+7])\n\t\toffset += railen\n\t}\n\tif i.Payload[0]>>3&0x01 == 1 {\n\t\tif l < (offset + tailen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar tai TAI\n\t\tuli.TAI = &tai\n\t\tuli.TAI.PLMN = &plmn\n\t\tuli.TAI.PLMN.MCC, uli.TAI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.TAI.TAC = binary.BigEndian.Uint16(i.Payload[offset+3 : offset+5])\n\t\toffset += tailen\n\n\t}\n\tif i.Payload[0]>>4&0x01 == 1 {\n\t\tif l < (offset + ecgilen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar ecgi ECGI\n\t\tuli.ECGI = &ecgi\n\t\tuli.ECGI.PLMN = &plmn\n\t\tuli.ECGI.PLMN.MCC, uli.ECGI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.ECGI.ECI = binary.BigEndian.Uint32(i.Payload[offset+3 : offset+7])\n\t\toffset += ecgilen\n\n\t}\n\tif i.Payload[0]>>5&0x01 == 1 {\n\t\tif l < (offset + lailen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar lai LAI\n\t\tuli.LAI = &lai\n\t\tuli.LAI.PLMN = &plmn\n\t\tuli.LAI.PLMN.MCC, uli.LAI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.LAI.LAC = binary.BigEndian.Uint16(i.Payload[offset+3 : offset+5])\n\t\toffset += lailen\n\t}\n\tif i.Payload[0]>>6&0x01 == 1 {\n\t\tif l < (offset + menbilen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar menbi MENBI\n\t\tuli.MENBI = &menbi\n\t\tuli.MENBI.PLMN = &plmn\n\t\tuli.MENBI.PLMN.MCC, uli.MENBI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.MENBI.MENBI = utils.Uint24To32(i.Payload[offset+3 : offset+6])\n\t\toffset += menbilen\n\t}\n\tif i.Payload[0]>>7&0x01 == 1 {\n\t\tif l < (offset + emenbilen) {\n\t\t\treturn &uli, io.ErrUnexpectedEOF\n\t\t}\n\t\tvar emenbi EMENBI\n\t\tuli.EMENBI = &emenbi\n\t\tuli.EMENBI.PLMN = &plmn\n\t\tuli.EMENBI.PLMN.MCC, uli.EMENBI.PLMN.MNC, _ = utils.DecodePLMN(i.Payload[offset : offset+3])\n\t\tuli.EMENBI.EMENBI = utils.Uint24To32(i.Payload[offset+3 : offset+6])\n\t}\n\treturn &uli, nil\n}\n"
  },
  {
    "path": "gtpv2/ie/uli_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nimport (\n\t\"testing\"\n)\n\nfunc TestNewUserLocationInformationStruct(t *testing.T) {\n\tt.Run(\"Test UserLocationInformation unmarshal\", func(t *testing.T) {\n\t\tuli := NewUserLocationInformationStruct(\n\t\t\tNewCGI(\"123\", \"45\", 0x1111, 0x2222),\n\t\t\tNewSAI(\"123\", \"45\", 0x1111, 0x3333),\n\t\t\tNewRAI(\"123\", \"45\", 0x1111, 0x4444),\n\t\t\tNewTAI(\"123\", \"45\", 0x5555),\n\t\t\tNewECGI(\"123\", \"45\", 0x66666666),\n\t\t\tNewLAI(\"123\", \"45\", 0x1111),\n\t\t\tNewMENBI(\"123\", \"45\", 0x11111111),\n\t\t\tNewEMENBI(\"123\", \"45\", 0x22222222),\n\t\t)\n\t\tif uli == nil {\n\t\t\tt.Fatalf(\"Error in NewUserLocationInformationStruct\")\n\t\t}\n\n\t\tuliFields, err := uli.UserLocationInformation()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Error in unmarshal: %v\", err)\n\t\t}\n\n\t\t// CGI\n\t\tif uliFields.CGI.LAC != 0x1111 {\n\t\t\tt.Errorf(\"wrong uliFields.CGI.LAC, got: 0x%x\", uliFields.CGI.LAC)\n\t\t}\n\t\tif uliFields.CGI.CI != 0x2222 {\n\t\t\tt.Errorf(\"wrong uliFields.CGI.CI, got: 0x%x\", uliFields.CGI.CI)\n\t\t}\n\t\tif uliFields.CGI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.CGI.PLMN.MCC, got: %v\", uliFields.CGI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.CGI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.CGI.PLMN.MNC, got: %v\", uliFields.CGI.PLMN.MNC)\n\t\t}\n\n\t\t// SAI\n\t\tif uliFields.SAI.LAC != 0x1111 {\n\t\t\tt.Errorf(\"wrong uliFields.SAI.LAC, got: 0x%x\", uliFields.SAI.LAC)\n\t\t}\n\t\tif uliFields.SAI.SAC != 0x3333 {\n\t\t\tt.Errorf(\"wrong uliFields.SAI.SAC, got: 0x%x\", uliFields.SAI.SAC)\n\t\t}\n\t\tif uliFields.SAI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.SAI.PLMN.MCC, got: %v\", uliFields.SAI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.SAI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.SAI.PLMN.MNC, got: %v\", uliFields.SAI.PLMN.MNC)\n\t\t}\n\n\t\t// RAI\n\t\tif uliFields.RAI.LAC != 0x1111 {\n\t\t\tt.Errorf(\"wrong uliFields.RAI.LAC, got: 0x%x\", uliFields.RAI.LAC)\n\t\t}\n\t\tif uliFields.RAI.RAC != 0x4444 {\n\t\t\tt.Errorf(\"wrong uliFields.RAI.RAC, got: 0x%x\", uliFields.RAI.RAC)\n\t\t}\n\t\tif uliFields.RAI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.RAI.PLMN.MCC, got: %v\", uliFields.RAI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.RAI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.RAI.PLMN.MNC, got: %v\", uliFields.RAI.PLMN.MNC)\n\t\t}\n\n\t\t// TAI\n\t\tif uliFields.TAI.TAC != 0x5555 {\n\t\t\tt.Errorf(\"wrong uliFields.TAI.TAC, got: 0x%x\", uliFields.TAI.TAC)\n\t\t}\n\t\tif uliFields.TAI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.TAI.PLMN.MCC, got: %v\", uliFields.TAI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.TAI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.TAI.PLMN.MNC, got: %v\", uliFields.TAI.PLMN.MNC)\n\t\t}\n\n\t\t// ECGI\n\t\tif uliFields.ECGI.ECI != 0x6666666 {\n\t\t\tt.Errorf(\"wrong uliFields.ECGI.ECI, got: 0x%x\", uliFields.ECGI.ECI)\n\t\t}\n\t\tif uliFields.ECGI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.ECGI.PLMN.MCC, got: %v\", uliFields.ECGI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.ECGI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.ECGI.PLMN.MNC, got: %v\", uliFields.ECGI.PLMN.MNC)\n\t\t}\n\n\t\t// LAI\n\t\tif uliFields.LAI.LAC != 0x1111 {\n\t\t\tt.Errorf(\"wrong uliFields.LAI.LAC, got: 0x%x\", uliFields.LAI.LAC)\n\t\t}\n\t\tif uliFields.LAI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.LAI.PLMN.MCC, got: %v\", uliFields.LAI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.LAI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.LAI.PLMN.MNC, got: %v\", uliFields.LAI.PLMN.MNC)\n\t\t}\n\n\t\t// MENBI\n\t\tif uliFields.MENBI.MENBI != 0x111111 {\n\t\t\tt.Errorf(\"wrong uliFields.MENBI.MENBI, got: 0x%x\", uliFields.MENBI.MENBI)\n\t\t}\n\t\tif uliFields.MENBI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.MENBI.PLMN.MCC, got: %v\", uliFields.MENBI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.MENBI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.MENBI.PLMN.MNC, got: %v\", uliFields.MENBI.PLMN.MNC)\n\t\t}\n\n\t\t// EMENBI\n\t\tif uliFields.EMENBI.EMENBI != 0x222222 {\n\t\t\tt.Errorf(\"wrong uliFields.EMENBI.EMENBI, got: 0x%x\", uliFields.EMENBI.EMENBI)\n\t\t}\n\t\tif uliFields.EMENBI.PLMN.MCC != \"123\" {\n\t\t\tt.Errorf(\"wrong uliFields.EMENBI.PLMN.MCC, got: %v\", uliFields.EMENBI.PLMN.MCC)\n\t\t}\n\t\tif uliFields.EMENBI.PLMN.MNC != \"45\" {\n\t\t\tt.Errorf(\"wrong uliFields.EMENBI.PLMN.MNC, got: %v\", uliFields.EMENBI.PLMN.MNC)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv2/ie/utils.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage ie\n\nfunc has8thBit(f uint8) bool {\n\treturn (f&0x80)>>7 == 1\n}\n\nfunc has7thBit(f uint8) bool {\n\treturn (f&0x40)>>6 == 1\n}\n\nfunc has6thBit(f uint8) bool {\n\treturn (f&0x20)>>5 == 1\n}\n\nfunc has5thBit(f uint8) bool {\n\treturn (f&0x010)>>4 == 1\n}\n\nfunc has4thBit(f uint8) bool {\n\treturn (f&0x08)>>3 == 1\n}\n\nfunc has3rdBit(f uint8) bool {\n\treturn (f&0x04)>>2 == 1\n}\n\nfunc has2ndBit(f uint8) bool {\n\treturn (f&0x02)>>1 == 1\n}\n\nfunc has1stBit(f uint8) bool {\n\treturn (f & 0x01) == 1\n}\n"
  },
  {
    "path": "gtpv2/logger.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\nimport (\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"sync\"\n)\n\nvar (\n\tlogger = log.New(os.Stderr, \"\", log.LstdFlags)\n\tlogMu  sync.Mutex\n)\n\n// SetLogger replaces the standard logger with arbitrary *log.Logger.\n//\n// This package prints just informational logs from goroutines working background\n// that might help developers test the program but can be ignored safely. More\n// important ones that needs any action by caller would be returned as errors.\nfunc SetLogger(l *log.Logger) {\n\tif l == nil {\n\t\tlog.Println(\"Don't pass nil to SetLogger: use DisableLogging instead.\")\n\t}\n\n\tsetLogger(l)\n}\n\n// EnableLogging enables the logging from the package.\n// If l is nil, it uses default logger provided by the package.\n// Logging is enabled by default.\n//\n// See also: SetLogger.\nfunc EnableLogging(l *log.Logger) {\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tsetLogger(l)\n}\n\n// DisableLogging disables the logging from the package.\n// Logging is enabled by default.\nfunc DisableLogging() {\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tlogger.SetOutput(io.Discard)\n}\n\nfunc setLogger(l *log.Logger) {\n\tif l == nil {\n\t\tl = log.New(os.Stderr, \"\", log.LstdFlags)\n\t}\n\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tlogger = l\n}\nfunc logf(format string, v ...interface{}) {\n\tlogMu.Lock()\n\tdefer logMu.Unlock()\n\n\tlogger.Printf(format, v...)\n}\n"
  },
  {
    "path": "gtpv2/message/change-notification-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ChangeNotificationRequest is a ChangeNotificationRequest Header and its IEs above.\ntype ChangeNotificationRequest struct {\n\t*Header\n\tIMSI                             *ie.IE\n\tMEI                              *ie.IE\n\tIndicationFlags                  *ie.IE\n\tRATType                          *ie.IE\n\tULI                              *ie.IE\n\tUCI                              *ie.IE\n\tPGWS5S8IPAddressForControlPlane  *ie.IE\n\tLinkedEBI                        *ie.IE\n\tPresenceReportingAreaInformation []*ie.IE\n\tMOExceptionDataCounter           *ie.IE\n\tSecondaryRATUsageDataReport      []*ie.IE\n\tPrivateExtension                 *ie.IE\n\tAdditionalIEs                    []*ie.IE\n}\n\n// NewChangeNotificationRequest creates a new ChangeNotificationRequest.\nfunc NewChangeNotificationRequest(teid, seq uint32, ies ...*ie.IE) *ChangeNotificationRequest {\n\tc := &ChangeNotificationRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeChangeNotificationRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tc.MEI = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.ULI = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.IPAddress:\n\t\t\tc.PGWS5S8IPAddressForControlPlane = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.PresenceReportingAreaInformation:\n\t\t\tc.PresenceReportingAreaInformation = append(c.PresenceReportingAreaInformation, i)\n\t\tcase ie.Counter:\n\t\t\tc.MOExceptionDataCounter = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tc.SecondaryRATUsageDataReport = append(c.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ChangeNotificationRequest into bytes.\nfunc (c *ChangeNotificationRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ChangeNotificationRequest into bytes.\nfunc (c *ChangeNotificationRequest) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MEI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWS5S8IPAddressForControlPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaInformation {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MOExceptionDataCounter; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.SecondaryRATUsageDataReport {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseChangeNotificationRequest decodes given bytes as ChangeNotificationRequest.\nfunc ParseChangeNotificationRequest(b []byte) (*ChangeNotificationRequest, error) {\n\tc := &ChangeNotificationRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ChangeNotificationRequest.\nfunc (c *ChangeNotificationRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tc.MEI = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.ULI = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.IPAddress:\n\t\t\tc.PGWS5S8IPAddressForControlPlane = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.PresenceReportingAreaInformation:\n\t\t\tc.PresenceReportingAreaInformation = append(c.PresenceReportingAreaInformation, i)\n\t\tcase ie.Counter:\n\t\t\tc.MOExceptionDataCounter = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tc.SecondaryRATUsageDataReport = append(c.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ChangeNotificationRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MEI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWS5S8IPAddressForControlPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaInformation {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MOExceptionDataCounter; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.SecondaryRATUsageDataReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ChangeNotificationRequest) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ChangeNotificationRequest) MessageTypeName() string {\n\treturn \"Change Notification Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ChangeNotificationRequest) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/change-notification-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestChangeNotificationRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewChangeNotificationRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewMobileEquipmentIdentity(\"123450123456789\"),\n\t\t\t\tie.NewIndication(\n\t\t\t\t\t1, 0, 1, 0, 0, 0, 0, 1,\n\t\t\t\t\t0, 0, 0, 0, 1, 0, 0, 0,\n\t\t\t\t\t0, 0, 0, 1, 0, 1, 0, 1,\n\t\t\t\t\t0, 0, 0, 1, 0, 0, 0, 0,\n\t\t\t\t\t1, 0, 0, 0, 1, 0, 0, 0,\n\t\t\t\t\t1, 0, 0, 0, 0, 0, 0, 1,\n\t\t\t\t\t0, 1, 0, 0, 0, 0, 0, 0,\n\t\t\t\t\t1, 0, 1, 0, 0, 0, 0, 0,\n\t\t\t\t\t0, 0, 0, 0, 0, 0, 0, 1,\n\t\t\t\t),\n\t\t\t\tie.NewRATType(gtpv2.RATTypeEUTRAN),\n\t\t\t\tie.NewUserLocationInformationStruct(\n\t\t\t\t\tie.NewCGI(\"123\", \"45\", 0x1111, 0x2222),\n\t\t\t\t\tie.NewSAI(\"123\", \"45\", 0x1111, 0x3333),\n\t\t\t\t\tie.NewRAI(\"123\", \"45\", 0x1111, 0x4444),\n\t\t\t\t\tie.NewTAI(\"123\", \"45\", 0x5555),\n\t\t\t\t\tie.NewECGI(\"123\", \"45\", 0x66666666),\n\t\t\t\t\tie.NewLAI(\"123\", \"45\", 0x1111),\n\t\t\t\t\tie.NewMENBI(\"123\", \"45\", 0x11111111),\n\t\t\t\t\tie.NewEMENBI(\"123\", \"45\", 0x22222222),\n\t\t\t\t),\n\t\t\t\tie.NewUserCSGInformation(\"123\", \"45\", 0x00ffffff, gtpv2.AccessModeHybrid, 0, gtpv2.CMICSG),\n\t\t\t\tie.NewIPAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\tie.NewPrivateExtension(10415, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x26, 0x00, 0x8c, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// MAI\n\t\t\t\t0x4b, 0x00, 0x08, 0x00, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9,\n\t\t\t\t// IndicationFlags\n\t\t\t\t0x4d, 0x00, 0x09, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40, 0xa0, 0x01,\n\t\t\t\t// RATType\n\t\t\t\t0x52, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t// ULI\n\t\t\t\t// --------------------------------------\n\t\t\t\t0x56, 0x00, 0x33, 0x00,\n\t\t\t\t// Flags\n\t\t\t\t0xff,\n\t\t\t\t// CGI\n\t\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x22, 0x22,\n\t\t\t\t// SAI\n\t\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x33, 0x33,\n\t\t\t\t// RAI\n\t\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x44, 0x44,\n\t\t\t\t// TAI\n\t\t\t\t0x21, 0xf3, 0x54, 0x55, 0x55,\n\t\t\t\t// ECGI\n\t\t\t\t0x21, 0xf3, 0x54, 0x06, 0x66, 0x66, 0x66,\n\t\t\t\t// RAI\n\t\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11,\n\t\t\t\t// Macro eNB ID\n\t\t\t\t0x21, 0xf3, 0x54, 0x11, 0x11, 0x11,\n\t\t\t\t// Extended Macro eNB ID\n\t\t\t\t0x21, 0xf3, 0x54, 0x22, 0x22, 0x22,\n\t\t\t\t// --------------------------------------\n\t\t\t\t// UCI\n\t\t\t\t0x91, 0x00, 0x08, 0x00, 0x21, 0xf3, 0x54, 0x00, 0xff, 0xff, 0xff, 0x41,\n\t\t\t\t// PGWS5S8IPAddressForControlPlane\n\t\t\t\t0x4a, 0x00, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// LinkedEBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// PrivateExtension\n\t\t\t\t0xff, 0x00, 0x06, 0x00, 0x28, 0xaf, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseChangeNotificationRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/change-notification-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ChangeNotificationResponse is a ChangeNotificationResponse Header and its IEs above.\ntype ChangeNotificationResponse struct {\n\t*Header\n\tIMSI                          *ie.IE\n\tMEI                           *ie.IE\n\tCause                         *ie.IE\n\tChangeReportingAction         *ie.IE\n\tCSGInformationReportingAction *ie.IE\n\tPresenceReportingAreaAction   []*ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewChangeNotificationResponse creates a new ChangeNotificationResponse.\nfunc NewChangeNotificationResponse(teid, seq uint32, ies ...*ie.IE) *ChangeNotificationResponse {\n\tc := &ChangeNotificationResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeChangeNotificationResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tc.MEI = i\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ChangeNotificationResponse into bytes.\nfunc (c *ChangeNotificationResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ChangeNotificationResponse into bytes.\nfunc (c *ChangeNotificationResponse) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MEI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseChangeNotificationResponse decodes given bytes as ChangeNotificationResponse.\nfunc ParseChangeNotificationResponse(b []byte) (*ChangeNotificationResponse, error) {\n\tc := &ChangeNotificationResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ChangeNotificationResponse.\nfunc (c *ChangeNotificationResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tc.MEI = i\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ChangeNotificationResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MEI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ChangeNotificationResponse) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ChangeNotificationResponse) MessageTypeName() string {\n\treturn \"Change Notification Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ChangeNotificationResponse) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/change-notification-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestChangeNotificationResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewChangeNotificationResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewMobileEquipmentIdentity(\"123450123456789\"),\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewPrivateExtension(10415, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x27, 0x00, 0x30, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// MAI\n\t\t\t\t0x4b, 0x00, 0x08, 0x00, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// PrivateExtension\n\t\t\t\t0xff, 0x00, 0x06, 0x00, 0x28, 0xaf, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseChangeNotificationResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/context-ack.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ContextAcknowledge is a ContextAcknowledge Header and its IEs above.\ntype ContextAcknowledge struct {\n\t*Header\n\tCause                  *ie.IE\n\tIndicationFlags        *ie.IE\n\tForwardingFTEID        *ie.IE\n\tBearerContexts         []*ie.IE\n\tSGSNNumber             *ie.IE\n\tMMENumberForMTSMS      *ie.IE\n\tSGSNIdentifierForMTSMS *ie.IE\n\tMMEIdentifierForMTSMS  *ie.IE\n\tPrivateExtension       *ie.IE\n\tAdditionalIEs          []*ie.IE\n}\n\n// NewContextAcknowledge creates a new ContextAcknowledge.\nfunc NewContextAcknowledge(teid, seq uint32, ies ...*ie.IE) *ContextAcknowledge {\n\tc := &ContextAcknowledge{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeContextAcknowledge, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.ForwardingFTEID = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.NodeNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNNumber = i\n\t\t\tcase 1:\n\t\t\t\tc.MMENumberForMTSMS = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.NodeIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNIdentifierForMTSMS = i\n\t\t\tcase 1:\n\t\t\t\tc.MMEIdentifierForMTSMS = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ContextAcknowledge into bytes.\nfunc (c *ContextAcknowledge) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ContextAcknowledge into bytes.\nfunc (c *ContextAcknowledge) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ForwardingFTEID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNumber; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMENumberForMTSMS; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNIdentifierForMTSMS; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMEIdentifierForMTSMS; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseContextAcknowledge decodes given bytes as ContextAcknowledge.\nfunc ParseContextAcknowledge(b []byte) (*ContextAcknowledge, error) {\n\tc := &ContextAcknowledge{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ContextAcknowledge.\nfunc (c *ContextAcknowledge) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.ForwardingFTEID = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.NodeNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNNumber = i\n\t\t\tcase 1:\n\t\t\t\tc.MMENumberForMTSMS = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.NodeIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNIdentifierForMTSMS = i\n\t\t\tcase 1:\n\t\t\t\tc.MMEIdentifierForMTSMS = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ContextAcknowledge) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ForwardingFTEID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNumber; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMENumberForMTSMS; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNIdentifierForMTSMS; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMEIdentifierForMTSMS; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ContextAcknowledge) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ContextAcknowledge) MessageTypeName() string {\n\treturn \"Context Acknowledge\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ContextAcknowledge) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/context-ack_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ContextAcknowledge into bytes.\n//\n// Deprecated: use ContextAcknowledge.Marshal instead.\nfunc (c *ContextAcknowledge) Serialize() ([]byte, error) {\n\tlog.Println(\"ContextAcknowledge.Serialize is deprecated. use ContextAcknowledge.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes ContextAcknowledge into bytes given as b.\n//\n// Deprecated: use ContextAcknowledge.MarshalTo instead.\nfunc (c *ContextAcknowledge) SerializeTo(b []byte) error {\n\tlog.Println(\"ContextAcknowledge.SerializeTo is deprecated. use ContextAcknowledge.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeContextAcknowledge decodes bytes as ContextAcknowledge.\n//\n// Deprecated: use ParseContextAcknowledge instead.\nfunc DecodeContextAcknowledge(b []byte) (*ContextAcknowledge, error) {\n\tlog.Println(\"DecodeContextAcknowledge is deprecated. use ParseContextAcknowledge instead\")\n\treturn ParseContextAcknowledge(b)\n}\n\n// DecodeFromBytes decodes bytes as ContextAcknowledge.\n//\n// Deprecated: use ContextAcknowledge.UnmarshalBinary instead.\nfunc (c *ContextAcknowledge) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ContextAcknowledge.DecodeFromBytes is deprecated. use ContextAcknowledge.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ContextAcknowledge.\n//\n// Deprecated: use ContextAcknowledge.MarshalLen instead.\nfunc (c *ContextAcknowledge) Len() int {\n\tlog.Println(\"ContextAcknowledge.Len is deprecated. use ContextAcknowledge.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/context-ack_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestContextAcknowledge(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewContextAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS4SGSNGTPU, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x84, 0x00, 0x47, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseContextAcknowledge(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/context-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ContextRequest is a ContextRequest Header and its IEs above.\ntype ContextRequest struct {\n\t*Header\n\tIMSI                               *ie.IE\n\tGUTI                               *ie.IE\n\tRAI                                *ie.IE\n\tPTMSI                              *ie.IE\n\tPTMSISignature                     *ie.IE\n\tCompleteTAURequestMessage          *ie.IE\n\tAddressAndTEIDForCPlane            *ie.IE\n\tUDPSourcePortNumber                *ie.IE\n\tRATType                            *ie.IE\n\tIndication                         *ie.IE\n\tHopCounter                         *ie.IE\n\tTargetPLMNID                       *ie.IE\n\tMMESGSNLDN                         *ie.IE\n\tSGSNNodeName                       *ie.IE\n\tMMENodeName                        *ie.IE\n\tSGSNNumber                         *ie.IE\n\tSGSNIdentifier                     *ie.IE\n\tMMEIdentifier                      *ie.IE\n\tCIoTOptimizationsSupportIndication *ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewContextRequest creates a new ContextRequest.\nfunc NewContextRequest(teid, seq uint32, ies ...*ie.IE) *ContextRequest {\n\tc := &ContextRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeContextRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.GUTI:\n\t\t\tc.GUTI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.RAI = i\n\t\tcase ie.PacketTMSI:\n\t\t\tc.PTMSI = i\n\t\tcase ie.PTMSISignature:\n\t\t\tc.PTMSISignature = i\n\t\tcase ie.CompleteRequestMessage:\n\t\t\tc.CompleteTAURequestMessage = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.AddressAndTEIDForCPlane = i\n\t\tcase ie.PortNumber:\n\t\t\tc.UDPSourcePortNumber = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.Indication:\n\t\t\tc.Indication = i\n\t\tcase ie.HopCounter:\n\t\t\tc.HopCounter = i\n\t\tcase ie.ServingNetwork:\n\t\t\tc.TargetPLMNID = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tc.MMESGSNLDN = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNNodeName = i\n\t\t\tcase 1:\n\t\t\t\tc.MMENodeName = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.NodeNumber:\n\t\t\tc.SGSNNumber = i\n\t\tcase ie.NodeIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.MMEIdentifier = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.CIoTOptimizationsSupportIndication:\n\t\t\tc.CIoTOptimizationsSupportIndication = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ContextRequest into bytes.\nfunc (c *ContextRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ContextRequest into bytes.\nfunc (c *ContextRequest) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.GUTI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RAI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PTMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PTMSISignature; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CompleteTAURequestMessage; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AddressAndTEIDForCPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UDPSourcePortNumber; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Indication; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HopCounter; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TargetPLMNID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNodeName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMENodeName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNumber; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMEIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CIoTOptimizationsSupportIndication; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseContextRequest decodes given bytes as ContextRequest.\nfunc ParseContextRequest(b []byte) (*ContextRequest, error) {\n\tc := &ContextRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ContextRequest.\nfunc (c *ContextRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.GUTI:\n\t\t\tc.GUTI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.RAI = i\n\t\tcase ie.PacketTMSI:\n\t\t\tc.PTMSI = i\n\t\tcase ie.PTMSISignature:\n\t\t\tc.PTMSISignature = i\n\t\tcase ie.CompleteRequestMessage:\n\t\t\tc.CompleteTAURequestMessage = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.AddressAndTEIDForCPlane = i\n\t\tcase ie.PortNumber:\n\t\t\tc.UDPSourcePortNumber = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.Indication:\n\t\t\tc.Indication = i\n\t\tcase ie.HopCounter:\n\t\t\tc.HopCounter = i\n\t\tcase ie.ServingNetwork:\n\t\t\tc.TargetPLMNID = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tc.MMESGSNLDN = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNNodeName = i\n\t\t\tcase 1:\n\t\t\t\tc.MMENodeName = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.NodeNumber:\n\t\t\tc.SGSNNumber = i\n\t\tcase ie.NodeIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.MMEIdentifier = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.CIoTOptimizationsSupportIndication:\n\t\t\tc.CIoTOptimizationsSupportIndication = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ContextRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.GUTI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RAI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PTMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PTMSISignature; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CompleteTAURequestMessage; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AddressAndTEIDForCPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UDPSourcePortNumber; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Indication; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HopCounter; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TargetPLMNID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNodeName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMENodeName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNumber; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMEIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CIoTOptimizationsSupportIndication; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ContextRequest) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ContextRequest) MessageTypeName() string {\n\treturn \"Context Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ContextRequest) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/context-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ContextRequest into bytes.\n//\n// Deprecated: use ContextRequest.Marshal instead.\nfunc (c *ContextRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"ContextRequest.Serialize is deprecated. use ContextRequest.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes ContextRequest into bytes given as b.\n//\n// Deprecated: use ContextRequest.MarshalTo instead.\nfunc (c *ContextRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"ContextRequest.SerializeTo is deprecated. use ContextRequest.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeContextRequest decodes bytes as ContextRequest.\n//\n// Deprecated: use ParseContextRequest instead.\nfunc DecodeContextRequest(b []byte) (*ContextRequest, error) {\n\tlog.Println(\"DecodeContextRequest is deprecated. use ParseContextRequest instead\")\n\treturn ParseContextRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as ContextRequest.\n//\n// Deprecated: use ContextRequest.UnmarshalBinary instead.\nfunc (c *ContextRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ContextRequest.DecodeFromBytes is deprecated. use ContextRequest.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ContextRequest.\n//\n// Deprecated: use ContextRequest.MarshalLen instead.\nfunc (c *ContextRequest) Len() int {\n\tlog.Println(\"ContextRequest.Len is deprecated. use ContextRequest.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/context-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestContextRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewContextRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewPacketTMSI(0xdeadbeef),\n\t\t\t\tie.NewPTMSISignature(0xbeebee),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x82, 0x00, 0x23, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// P-TMSI\n\t\t\t\t0x6f, 0x00, 0x04, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// P-TMSI Signature\n\t\t\t\t0x70, 0x00, 0x03, 0x00, 0xbe, 0xeb, 0xee,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseContextRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/context-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ContextResponse is a ContextResponse Header and its IEs above.\ntype ContextResponse struct {\n\t*Header\n\tCause                               *ie.IE\n\tIMSI                                *ie.IE\n\tUEMMContext                         *ie.IE\n\tUEPDNConnections                    []*ie.IE\n\tSenderFTEID                         *ie.IE\n\tSGWS11S4FTEID                       *ie.IE\n\tSGWNodeName                         *ie.IE\n\tIndicationFlags                     *ie.IE\n\tTraceInformation                    *ie.IE\n\tS101IPAddress                       *ie.IE\n\tS102IPAddress                       *ie.IE\n\tSubscribedRFSPIndex                 *ie.IE\n\tRFSPIndexInUse                      *ie.IE\n\tUETimeZone                          *ie.IE\n\tMMESGSNLDN                          *ie.IE\n\tMDTConfiguration                    *ie.IE\n\tSGSNNodeName                        *ie.IE\n\tMMENodeName                         *ie.IE\n\tUCI                                 *ie.IE\n\tMonitoringEventInformation          *ie.IE\n\tMonitoringEventExtensionInformation *ie.IE\n\tUEUsageType                         *ie.IE\n\tSCEFPDNConnection                   []*ie.IE\n\tRATType                             *ie.IE\n\tServingPLMNRateControl              *ie.IE\n\tMOExceptionDataCounter              *ie.IE\n\tRemainingRunningServiceGapTimer     *ie.IE\n\tExtendedTraceInformation            *ie.IE\n\tSubscribedAdditionalRRMPolicyIndex  *ie.IE\n\tAdditionalRRMPolicyIndexInUse       *ie.IE\n\tPrivateExtension                    *ie.IE\n\tAdditionalIEs                       []*ie.IE\n}\n\n// NewContextResponse creates a new ContextResponse.\nfunc NewContextResponse(teid, seq uint32, ies ...*ie.IE) *ContextResponse {\n\tc := &ContextResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeContextResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MMContextEPSSecurityContextQuadrupletsAndQuintuplets,\n\t\t\tie.MMContextGSMKeyAndTriplets, ie.MMContextGSMKeyUsedCipherAndQuintuplets,\n\t\t\tie.MMContextUMTSKeyAndQuintuplets, ie.MMContextUMTSKeyQuadrupletsAndQuintuplets,\n\t\t\tie.MMContextUMTSKeyUsedCipherAndQuintuplets:\n\t\t\tif c.UEMMContext != nil {\n\t\t\t\tc.UEMMContext = i\n\t\t\t} else {\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PDNConnection:\n\t\t\tc.UEPDNConnections = append(c.UEPDNConnections, i)\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SenderFTEID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWS11S4FTEID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGWNodeName = i\n\t\t\tcase 1:\n\t\t\t\tc.SGSNNodeName = i\n\t\t\tcase 2:\n\t\t\t\tc.MMENodeName = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.TraceInformation:\n\t\t\tc.TraceInformation = i\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.S101IPAddress = i\n\t\t\tcase 1:\n\t\t\t\tc.S102IPAddress = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.RFSPIndex:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SubscribedRFSPIndex = i\n\t\t\tcase 1:\n\t\t\t\tc.RFSPIndexInUse = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tc.MMESGSNLDN = i\n\t\tcase ie.MDTConfiguration:\n\t\t\tc.MDTConfiguration = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.MonitoringEventInformation:\n\t\t\tc.MonitoringEventInformation = i\n\t\tcase ie.MonitoringEventExtensionInformation:\n\t\t\tc.MonitoringEventExtensionInformation = i\n\t\tcase ie.IntegerNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUsageType = i\n\t\t\tcase 1:\n\t\t\t\tc.RemainingRunningServiceGapTimer = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.SCEFPDNConnection:\n\t\t\tc.SCEFPDNConnection = append(c.SCEFPDNConnection, i)\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.ServingPLMNRateControl:\n\t\t\tc.ServingPLMNRateControl = i\n\t\tcase ie.Counter:\n\t\t\tc.MOExceptionDataCounter = i\n\t\tcase ie.ExtendedTraceInformation:\n\t\t\tc.ExtendedTraceInformation = i\n\t\tcase ie.AdditionalRRMPolicyIndex:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SubscribedAdditionalRRMPolicyIndex = i\n\t\t\tcase 1:\n\t\t\t\tc.AdditionalRRMPolicyIndexInUse = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ContextResponse into bytes.\nfunc (c *ContextResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ContextResponse into bytes.\nfunc (c *ContextResponse) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UEMMContext; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.UEPDNConnections {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWS11S4FTEID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TraceInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.S101IPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.S102IPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SubscribedRFSPIndex; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RFSPIndexInUse; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MDTConfiguration; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNodeName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMENodeName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MonitoringEventInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UEUsageType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.SCEFPDNConnection {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ServingPLMNRateControl; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MOExceptionDataCounter; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RemainingRunningServiceGapTimer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedTraceInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseContextResponse decodes given bytes as ContextResponse.\nfunc ParseContextResponse(b []byte) (*ContextResponse, error) {\n\tc := &ContextResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ContextResponse.\nfunc (c *ContextResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MMContextEPSSecurityContextQuadrupletsAndQuintuplets,\n\t\t\tie.MMContextGSMKeyAndTriplets, ie.MMContextGSMKeyUsedCipherAndQuintuplets,\n\t\t\tie.MMContextUMTSKeyAndQuintuplets, ie.MMContextUMTSKeyQuadrupletsAndQuintuplets,\n\t\t\tie.MMContextUMTSKeyUsedCipherAndQuintuplets:\n\t\t\tif c.UEMMContext != nil {\n\t\t\t\tc.UEMMContext = i\n\t\t\t} else {\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PDNConnection:\n\t\t\tc.UEPDNConnections = append(c.UEPDNConnections, i)\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SenderFTEID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWS11S4FTEID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SGWNodeName = i\n\t\t\tcase 1:\n\t\t\t\tc.SGSNNodeName = i\n\t\t\tcase 2:\n\t\t\t\tc.MMENodeName = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.TraceInformation:\n\t\t\tc.TraceInformation = i\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.S101IPAddress = i\n\t\t\tcase 1:\n\t\t\t\tc.S102IPAddress = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.RFSPIndex:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SubscribedRFSPIndex = i\n\t\t\tcase 1:\n\t\t\t\tc.RFSPIndexInUse = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tc.MMESGSNLDN = i\n\t\tcase ie.MDTConfiguration:\n\t\t\tc.MDTConfiguration = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.MonitoringEventInformation:\n\t\t\tc.MonitoringEventInformation = i\n\t\tcase ie.IntegerNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUsageType = i\n\t\t\tcase 1:\n\t\t\t\tc.RemainingRunningServiceGapTimer = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.SCEFPDNConnection:\n\t\t\tc.SCEFPDNConnection = append(c.SCEFPDNConnection, i)\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.ServingPLMNRateControl:\n\t\t\tc.ServingPLMNRateControl = i\n\t\tcase ie.Counter:\n\t\t\tc.MOExceptionDataCounter = i\n\t\tcase ie.ExtendedTraceInformation:\n\t\t\tc.ExtendedTraceInformation = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ContextResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UEMMContext; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.UEPDNConnections {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWS11S4FTEID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TraceInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.S101IPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.S102IPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SubscribedRFSPIndex; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RFSPIndexInUse; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MDTConfiguration; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGSNNodeName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMENodeName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MonitoringEventInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UEUsageType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.SCEFPDNConnection {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ServingPLMNRateControl; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MOExceptionDataCounter; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RemainingRunningServiceGapTimer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ExtendedTraceInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ContextResponse) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ContextResponse) MessageTypeName() string {\n\treturn \"Context Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ContextResponse) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/context-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ContextResponse into bytes.\n//\n// Deprecated: use ContextResponse.Marshal instead.\nfunc (c *ContextResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"ContextResponse.Serialize is deprecated. use ContextResponse.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes ContextResponse into bytes given as b.\n//\n// Deprecated: use ContextResponse.MarshalTo instead.\nfunc (c *ContextResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"ContextResponse.SerializeTo is deprecated. use ContextResponse.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeContextResponse decodes bytes as ContextResponse.\n//\n// Deprecated: use ParseContextResponse instead.\nfunc DecodeContextResponse(b []byte) (*ContextResponse, error) {\n\tlog.Println(\"DecodeContextResponse is deprecated. use ParseContextResponse instead\")\n\treturn ParseContextResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as ContextResponse.\n//\n// Deprecated: use ContextResponse.UnmarshalBinary instead.\nfunc (c *ContextResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ContextResponse.DecodeFromBytes is deprecated. use ContextResponse.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ContextResponse.\n//\n// Deprecated: use ContextResponse.MarshalLen instead.\nfunc (c *ContextResponse) Len() int {\n\tlog.Println(\"ContextResponse.Len is deprecated. use ContextResponse.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/context-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestContextResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewContextResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\t// ie.NewMMContext(), TODO: implement!\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS10MMEGTPC, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x83, 0x00, 0x27, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8c, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseContextResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/create-bearer-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// CreateBearerRequest is a CreateBearerRequest Header and its IEs above.\ntype CreateBearerRequest struct {\n\t*Header\n\tPTI                           *ie.IE\n\tLinkedEBI                     *ie.IE\n\tPCO                           *ie.IE\n\tBearerContexts                []*ie.IE\n\tPGWFQCSID                     *ie.IE\n\tSGWFQCSID                     *ie.IE\n\tChangeReportingAction         *ie.IE\n\tCSGInformationReportingAction *ie.IE\n\tHeNBInformationReporting      *ie.IE\n\tPresenceReportingAreaAction   []*ie.IE\n\tIndicationFlags               *ie.IE\n\tPGWNodeLoadControlInformation *ie.IE\n\tPGWAPNLoadControlInformation  *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tNBIFOMContainer               *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewCreateBearerRequest creates a new CreateBearerRequest.\nfunc NewCreateBearerRequest(teid, seq uint32, ies ...*ie.IE) *CreateBearerRequest {\n\tc := &CreateBearerRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeCreateBearerRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.ProcedureTransactionID:\n\t\t\tc.PTI = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tc.HeNBInformationReporting = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes CreateBearerRequest into bytes.\nfunc (c *CreateBearerRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes CreateBearerRequest into bytes.\nfunc (c *CreateBearerRequest) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.PTI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBInformationReporting; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWAPNLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreateBearerRequest decodes given bytes as CreateBearerRequest.\nfunc ParseCreateBearerRequest(b []byte) (*CreateBearerRequest, error) {\n\tc := &CreateBearerRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as CreateBearerRequest.\nfunc (c *CreateBearerRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tswitch i.Type {\n\t\tcase ie.ProcedureTransactionID:\n\t\t\tc.PTI = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tc.HeNBInformationReporting = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *CreateBearerRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.PTI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBInformationReporting; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWAPNLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreateBearerRequest) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreateBearerRequest) MessageTypeName() string {\n\treturn \"Create Bearer Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *CreateBearerRequest) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/create-bearer-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreateBearerRequest into bytes.\n//\n// Deprecated: use CreateBearerRequest.Marshal instead.\nfunc (c *CreateBearerRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"CreateBearerRequest.Serialize is deprecated. use CreateBearerRequest.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreateBearerRequest into bytes given as b.\n//\n// Deprecated: use CreateBearerRequest.MarshalTo instead.\nfunc (c *CreateBearerRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"CreateBearerRequest.SerializeTo is deprecated. use CreateBearerRequest.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreateBearerRequest decodes bytes as CreateBearerRequest.\n//\n// Deprecated: use ParseCreateBearerRequest instead.\nfunc DecodeCreateBearerRequest(b []byte) (*CreateBearerRequest, error) {\n\tlog.Println(\"DecodeCreateBearerRequest is deprecated. use ParseCreateBearerRequest instead\")\n\treturn ParseCreateBearerRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as CreateBearerRequest.\n//\n// Deprecated: use CreateBearerRequest.UnmarshalBinary instead.\nfunc (c *CreateBearerRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreateBearerRequest.DecodeFromBytes is deprecated. use CreateBearerRequest.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreateBearerRequest.\n//\n// Deprecated: use CreateBearerRequest.MarshalLen instead.\nfunc (c *CreateBearerRequest) Len() int {\n\tlog.Println(\"CreateBearerRequest.Len is deprecated. use CreateBearerRequest.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/create-bearer-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestCreateBearerRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewCreateBearerRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewEPSBearerID(5),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0),\n\t\t\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t\t\t\tie.NewBearerTFTCreateNewTFT(\n\t\t\t\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv4LocalAddress(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddress(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), net.CIDRMask(64, 128),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddressPrefixLength(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv6LocalAddressPrefixLength(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFDownlinkOnly, 2, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentProtocolIdentifierNextHeader(1),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSingleLocalPort(2152),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSingleRemotePort(2123),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentLocalPortRange(2123, 2152),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentRemotePortRange(2152, 2123),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFUplinkOnly, 3, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSecurityParameterIndex(0xdeadbeef),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentTypeOfServiceTrafficClass(1, 2),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentFlowLabel(0x00011111),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDestinationMACAddress(mac1),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSourceMACAddress(mac2),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFBidirectional, 4, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGVID(0x0111),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGVID(0x0222),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGPCPDEI(3),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGPCPDEI(5),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentEthertype(0x0800),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[]*ie.TFTParameter{\n\t\t\t\t\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\t\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\t\t\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(6),\n\t\t\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t\t\t\tie.NewBearerTFTCreateNewTFT(\n\t\t\t\t\t\t[]*ie.TFTPacketFilter{\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFPreRel7TFTFilter, 1, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv4RemoteAddress(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv4LocalAddress(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"127.0.0.1\"), net.IPv4Mask(255, 255, 255, 0),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddress(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), net.CIDRMask(64, 128),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv6RemoteAddressPrefixLength(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentIPv6LocalAddressPrefixLength(\n\t\t\t\t\t\t\t\t\tnet.ParseIP(\"2001::1\"), 64,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFDownlinkOnly, 2, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentProtocolIdentifierNextHeader(1),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSingleLocalPort(2152),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSingleRemotePort(2123),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentLocalPortRange(2123, 2152),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentRemotePortRange(2152, 2123),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFUplinkOnly, 3, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSecurityParameterIndex(0xdeadbeef),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentTypeOfServiceTrafficClass(1, 2),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentFlowLabel(0x00011111),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDestinationMACAddress(mac1),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentSourceMACAddress(mac2),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tie.NewTFTPacketFilter(\n\t\t\t\t\t\t\t\tie.TFTPFBidirectional, 4, 0,\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGVID(0x0111),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGVID(0x0222),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QCTAGPCPDEI(3),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentDot1QSTAGPCPDEI(5),\n\t\t\t\t\t\t\t\tie.NewTFTPFComponentEthertype(0x0800),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[]*ie.TFTParameter{\n\t\t\t\t\t\t\tie.NewTFTParameter(ie.TFTParamIDAuthorizationToken, []byte{0xde, 0xad, 0xbe, 0xef}),\n\t\t\t\t\t\t\tie.NewTFTParameter(ie.TFTParamIDFlowIdentifier, []byte{0x11, 0x11, 0x22, 0x22}),\n\t\t\t\t\t\t\tie.NewTFTParameter(ie.TFTParamIDPacketFileterIdentifier, []byte{0x01, 0x02, 0x03, 0x04}),\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x5f, 0x01, 0xb9, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0xd2, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x00,\n\t\t\t\t//   BearerQoS\n\t\t\t\t0x50, 0x00, 0x16, 0x00, 0x49, 0xff,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t//   BearerTFT\n\t\t\t\t0x54, 0x00, 0xaf, 0x00, 0x34, 0x01, 0x00, 0x57, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff,\n\t\t\t\t0x00, 0x11, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,\n\t\t\t\t0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x01, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x23, 0x20, 0x01,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x12,\n\t\t\t\t0x00, 0x12, 0x30, 0x01, 0x40, 0x08, 0x68, 0x50, 0x08, 0x4b, 0x41, 0x08, 0x4b, 0x08, 0x68, 0x51,\n\t\t\t\t0x08, 0x68, 0x08, 0x4b, 0x23, 0x00, 0x1a, 0x60, 0xde, 0xad, 0xbe, 0xef, 0x70, 0x01, 0x02, 0x80,\n\t\t\t\t0x01, 0x11, 0x11, 0x81, 0x12, 0x34, 0x56, 0x78, 0x90, 0x01, 0x82, 0x12, 0x34, 0x56, 0x78, 0x90,\n\t\t\t\t0x02, 0x34, 0x00, 0x0d, 0x83, 0x01, 0x11, 0x84, 0x02, 0x22, 0x85, 0x03, 0x86, 0x05, 0x87, 0x08,\n\t\t\t\t0x00, 0x01, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x02, 0x04, 0x11, 0x11, 0x22, 0x22, 0x03, 0x04, 0x01,\n\t\t\t\t0x02, 0x03, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0xd2, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   BearerQoS\n\t\t\t\t0x50, 0x00, 0x16, 0x00, 0x49, 0xff,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t//   BearerTFT\n\t\t\t\t0x54, 0x00, 0xaf, 0x00, 0x34, 0x01, 0x00, 0x57, 0x10, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff,\n\t\t\t\t0x00, 0x11, 0x7f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,\n\t\t\t\t0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x01, 0x00, 0x00,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x23, 0x20, 0x01,\n\t\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x12,\n\t\t\t\t0x00, 0x12, 0x30, 0x01, 0x40, 0x08, 0x68, 0x50, 0x08, 0x4b, 0x41, 0x08, 0x4b, 0x08, 0x68, 0x51,\n\t\t\t\t0x08, 0x68, 0x08, 0x4b, 0x23, 0x00, 0x1a, 0x60, 0xde, 0xad, 0xbe, 0xef, 0x70, 0x01, 0x02, 0x80,\n\t\t\t\t0x01, 0x11, 0x11, 0x81, 0x12, 0x34, 0x56, 0x78, 0x90, 0x01, 0x82, 0x12, 0x34, 0x56, 0x78, 0x90,\n\t\t\t\t0x02, 0x34, 0x00, 0x0d, 0x83, 0x01, 0x11, 0x84, 0x02, 0x22, 0x85, 0x03, 0x86, 0x05, 0x87, 0x08,\n\t\t\t\t0x00, 0x01, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x02, 0x04, 0x11, 0x11, 0x22, 0x22, 0x03, 0x04, 0x01,\n\t\t\t\t0x02, 0x03, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreateBearerRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/create-bearer-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// CreateBearerResponse is a CreateBearerResponse Header and its IEs above.\ntype CreateBearerResponse struct {\n\t*Header\n\tCause                              *ie.IE\n\tBearerContexts                     []*ie.IE\n\tRecovery                           *ie.IE\n\tMMEFQCSID                          *ie.IE\n\tSGWFQCSID                          *ie.IE\n\tEPDGFQCSID                         *ie.IE\n\tTWANFQCSID                         *ie.IE\n\tPCO                                *ie.IE\n\tUETimeZone                         *ie.IE\n\tULI                                *ie.IE\n\tTWANIdentifier                     *ie.IE\n\tMMEOverloadControlInformation      *ie.IE\n\tSGWOverloadControlInformation      *ie.IE\n\tPresenceReportingAction            []*ie.IE\n\tMMESGSNIdentifier                  *ie.IE\n\tTWANePDGOverloadControlInformation *ie.IE\n\tWLANLocationInformation            *ie.IE\n\tWLANLocationTimestamp              *ie.IE\n\tUELocalIPAddress                   *ie.IE\n\tUEUDPPort                          *ie.IE\n\tNBIFOMContainer                    *ie.IE\n\tUETCPPort                          *ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewCreateBearerResponse creates a new CreateBearerResponse.\nfunc NewCreateBearerResponse(teid, seq uint32, ies ...*ie.IE) *CreateBearerResponse {\n\tc := &CreateBearerResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeCreateBearerResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.ULI = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationTimestamp = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAction = append(c.PresenceReportingAction, i)\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.UELocalIPAddress = i\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tc.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes CreateBearerResponse into bytes.\nfunc (c *CreateBearerResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes CreateBearerResponse into bytes.\nfunc (c *CreateBearerResponse) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMEOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAction {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANePDGOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationTimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UELocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UEUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETCPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreateBearerResponse decodes given bytes as CreateBearerResponse.\nfunc ParseCreateBearerResponse(b []byte) (*CreateBearerResponse, error) {\n\tc := &CreateBearerResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as CreateBearerResponse.\nfunc (c *CreateBearerResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANFQCSID = i\n\t\t\t}\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.ULI = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationInformation = i\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tif i.Instance() == 1 {\n\t\t\t\tc.WLANLocationTimestamp = i\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.TWANePDGOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAction = append(c.PresenceReportingAction, i)\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.UELocalIPAddress = i\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tc.UETCPPort = i\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *CreateBearerResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMEOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANePDGOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationTimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UELocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UEUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETCPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreateBearerResponse) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreateBearerResponse) MessageTypeName() string {\n\treturn \"Create Bearer Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *CreateBearerResponse) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/create-bearer-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreateBearerResponse into bytes.\n//\n// Deprecated: use CreateBearerResponse.Marshal instead.\nfunc (c *CreateBearerResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"CreateBearerResponse.Serialize is deprecated. use CreateBearerResponse.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreateBearerResponse into bytes given as b.\n//\n// Deprecated: use CreateBearerResponse.MarshalTo instead.\nfunc (c *CreateBearerResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"CreateBearerResponse.SerializeTo is deprecated. use CreateBearerResponse.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreateBearerResponse decodes bytes as CreateBearerResponse.\n//\n// Deprecated: use ParseCreateBearerResponse instead.\nfunc DecodeCreateBearerResponse(b []byte) (*CreateBearerResponse, error) {\n\tlog.Println(\"DecodeCreateBearerResponse is deprecated. use ParseCreateBearerResponse instead\")\n\treturn ParseCreateBearerResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as CreateBearerResponse.\n//\n// Deprecated: use CreateBearerResponse.UnmarshalBinary instead.\nfunc (c *CreateBearerResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreateBearerResponse.DecodeFromBytes is deprecated. use CreateBearerResponse.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreateBearerResponse.\n//\n// Deprecated: use CreateBearerResponse.MarshalLen instead.\nfunc (c *CreateBearerResponse) Len() int {\n\tlog.Println(\"CreateBearerResponse.Len is deprecated. use CreateBearerResponse.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/create-bearer-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestCreateBearerResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewCreateBearerResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0),\n\t\t\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(6),\n\t\t\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x60, 0x00, 0x54, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x1f, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x00,\n\t\t\t\t//   BearerQoS\n\t\t\t\t0x50, 0x00, 0x16, 0x00, 0x49, 0xff,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x1f, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   BearerQoS\n\t\t\t\t0x50, 0x00, 0x16, 0x00, 0x49, 0xff,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreateBearerResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/create-session-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// CreateSessionRequest is a CreateSessionRequest Header and its IEs above.\ntype CreateSessionRequest struct {\n\t*Header\n\tIMSI                               *ie.IE\n\tMSISDN                             *ie.IE\n\tMEI                                *ie.IE\n\tULI                                *ie.IE\n\tServingNetwork                     *ie.IE\n\tRATType                            *ie.IE\n\tIndicationFlags                    *ie.IE\n\tSenderFTEIDC                       *ie.IE\n\tPGWS5S8FTEIDC                      *ie.IE\n\tAPN                                *ie.IE\n\tSelectionMode                      *ie.IE\n\tPDNType                            *ie.IE\n\tPAA                                *ie.IE\n\tAPNRestriction                     *ie.IE\n\tAMBR                               *ie.IE\n\tLinkedEBI                          *ie.IE\n\tTWMI                               *ie.IE\n\tPCO                                *ie.IE\n\tBearerContextsToBeCreated          []*ie.IE\n\tBearerContextsToBeRemoved          []*ie.IE\n\tTraceInformation                   *ie.IE\n\tRecovery                           *ie.IE\n\tMMEFQCSID                          *ie.IE\n\tSGWFQCSID                          *ie.IE\n\tEPDGFQCSID                         *ie.IE\n\tTWANFQCSID                         *ie.IE\n\tUETimeZone                         *ie.IE\n\tUCI                                *ie.IE\n\tChargingCharacteristics            *ie.IE\n\tMMESGSNLDN                         *ie.IE\n\tSGWLDN                             *ie.IE\n\tEPDGLDN                            *ie.IE\n\tTWANLDN                            *ie.IE\n\tSignallingPriorityIndication       *ie.IE\n\tUELocalIPAddress                   *ie.IE\n\tUEUDPPort                          *ie.IE\n\tAPCO                               *ie.IE\n\tHeNBLocalIPAddress                 *ie.IE\n\tHeNBUDPPort                        *ie.IE\n\tMMESGSNIdentifier                  *ie.IE\n\tTWANIdentifier                     *ie.IE\n\tEPDGIPAddress                      *ie.IE\n\tCNOperatorSelectionEntity          *ie.IE\n\tPresenceReportingAreaInformation   []*ie.IE\n\tMMESGSNOverloadControlInformation  *ie.IE\n\tSGWOverloadControlInformation      *ie.IE\n\tTWANePDGOverloadControlInformation *ie.IE\n\tOriginationTimeStamp               *ie.IE\n\tMaximumWaitTime                    *ie.IE\n\tWLANLocationInformation            *ie.IE\n\tWLANLocationTimeStamp              *ie.IE\n\tNBIFOMContainer                    *ie.IE\n\tRemoteUEContextConnected           []*ie.IE\n\tTGPPAAAServerIdentifier            *ie.IE\n\tEPCO                               *ie.IE\n\tServingPLMNRateControl             *ie.IE\n\tMOExceptionDataCounter             *ie.IE\n\tUETCPPort                          *ie.IE\n\tMappedUEUsageType                  *ie.IE\n\tULIForSGW                          *ie.IE\n\tSGWUNodeName                       *ie.IE\n\tSecondaryRATUsageDataReport        []*ie.IE\n\tUPFunctionSelectionIndicationFlags *ie.IE\n\tAPNRateControlStatus               *ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewCreateSessionRequest creates a new CreateSessionRequest.\nfunc NewCreateSessionRequest(teid, seq uint32, ies ...*ie.IE) *CreateSessionRequest {\n\tc := &CreateSessionRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeCreateSessionRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MSISDN:\n\t\t\tc.MSISDN = i\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tc.MEI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.ULI = i\n\t\t\tcase 1:\n\t\t\t\tc.ULIForSGW = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ServingNetwork:\n\t\t\tc.ServingNetwork = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SenderFTEIDC = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWS5S8FTEIDC = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.AccessPointName:\n\t\t\tc.APN = i\n\t\tcase ie.SelectionMode:\n\t\t\tc.SelectionMode = i\n\t\tcase ie.PDNType:\n\t\t\tc.PDNType = i\n\t\tcase ie.PDNAddressAllocation:\n\t\t\tc.PAA = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.AMBR = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.TrustedWLANModeIndication:\n\t\t\tc.TWMI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.BearerContextsToBeCreated = append(c.BearerContextsToBeCreated, i)\n\t\t\tcase 1:\n\t\t\t\tc.BearerContextsToBeRemoved = append(c.BearerContextsToBeRemoved, i)\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TraceInformation:\n\t\t\tc.TraceInformation = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.ChargingCharacteristics:\n\t\t\tc.ChargingCharacteristics = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNLDN = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWLDN = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGLDN = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANLDN = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.SignallingPriorityIndication:\n\t\t\tc.SignallingPriorityIndication = i\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UELocalIPAddress = i\n\t\t\tcase 1:\n\t\t\t\tc.HeNBLocalIPAddress = i\n\t\t\tcase 2:\n\t\t\t\tc.MMESGSNIdentifier = i\n\t\t\tcase 3:\n\t\t\t\tc.EPDGIPAddress = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tc.HeNBUDPPort = i\n\t\t\tcase 2:\n\t\t\t\tc.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.AdditionalProtocolConfigurationOptions:\n\t\t\tc.APCO = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationInformation = i\n\t\t\t}\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tc.CNOperatorSelectionEntity = i\n\t\tcase ie.PresenceReportingAreaInformation:\n\t\t\tc.PresenceReportingAreaInformation = append(c.PresenceReportingAreaInformation, i)\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.MillisecondTimeStamp:\n\t\t\tc.OriginationTimeStamp = i\n\t\tcase ie.IntegerNumber:\n\t\t\tc.MaximumWaitTime = i\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tc.WLANLocationTimeStamp = i\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.RemoteUEContext:\n\t\t\tc.RemoteUEContextConnected = append(c.RemoteUEContextConnected, i)\n\t\tcase ie.NodeIdentifier:\n\t\t\tc.TGPPAAAServerIdentifier = i\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\tc.EPCO = i\n\t\tcase ie.ServingPLMNRateControl:\n\t\t\tc.ServingPLMNRateControl = i\n\t\tcase ie.Counter:\n\t\t\tc.MOExceptionDataCounter = i\n\t\tcase ie.MappedUEUsageType:\n\t\t\tc.MappedUEUsageType = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tc.SGWUNodeName = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tc.SecondaryRATUsageDataReport = append(c.SecondaryRATUsageDataReport, i)\n\t\tcase ie.UPFunctionSelectionIndicationFlags:\n\t\t\tc.UPFunctionSelectionIndicationFlags = i\n\t\tcase ie.APNRateControlStatus:\n\t\t\tc.APNRateControlStatus = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes CreateSessionRequest into bytes.\nfunc (c *CreateSessionRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes CreateSessionRequest into bytes.\nfunc (c *CreateSessionRequest) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MSISDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MEI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ServingNetwork; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWS5S8FTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SelectionMode; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PDNType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PAA; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AMBR; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWMI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContextsToBeCreated {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContextsToBeRemoved {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TraceInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingCharacteristics; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SignallingPriorityIndication; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UELocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UEUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBLocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CNOperatorSelectionEntity; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaInformation {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANePDGOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.OriginationTimeStamp; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MaximumWaitTime; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationTimeStamp; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.RemoteUEContextConnected {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TGPPAAAServerIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ServingPLMNRateControl; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MOExceptionDataCounter; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETCPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MappedUEUsageType; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ULIForSGW; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWUNodeName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.SecondaryRATUsageDataReport {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UPFunctionSelectionIndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNRateControlStatus; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreateSessionRequest decodes given bytes as CreateSessionRequest.\nfunc ParseCreateSessionRequest(b []byte) (*CreateSessionRequest, error) {\n\tc := &CreateSessionRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as CreateSessionRequest.\nfunc (c *CreateSessionRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.MSISDN:\n\t\t\tc.MSISDN = i\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tc.MEI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.ULI = i\n\t\t\tcase 1:\n\t\t\t\tc.ULIForSGW = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ServingNetwork:\n\t\t\tc.ServingNetwork = i\n\t\tcase ie.RATType:\n\t\t\tc.RATType = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SenderFTEIDC = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWS5S8FTEIDC = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.AccessPointName:\n\t\t\tc.APN = i\n\t\tcase ie.SelectionMode:\n\t\t\tc.SelectionMode = i\n\t\tcase ie.PDNType:\n\t\t\tc.PDNType = i\n\t\tcase ie.PDNAddressAllocation:\n\t\t\tc.PAA = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.AMBR = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.TrustedWLANModeIndication:\n\t\t\tc.TWMI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.BearerContextsToBeCreated = append(c.BearerContextsToBeCreated, i)\n\t\t\tcase 1:\n\t\t\t\tc.BearerContextsToBeRemoved = append(c.BearerContextsToBeRemoved, i)\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TraceInformation:\n\t\t\tc.TraceInformation = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.UserCSGInformation:\n\t\t\tc.UCI = i\n\t\tcase ie.ChargingCharacteristics:\n\t\t\tc.ChargingCharacteristics = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNLDN = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWLDN = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGLDN = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANLDN = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.SignallingPriorityIndication:\n\t\t\tc.SignallingPriorityIndication = i\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UELocalIPAddress = i\n\t\t\tcase 1:\n\t\t\t\tc.HeNBLocalIPAddress = i\n\t\t\tcase 2:\n\t\t\t\tc.MMESGSNIdentifier = i\n\t\t\tcase 3:\n\t\t\t\tc.EPDGIPAddress = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tc.HeNBUDPPort = i\n\t\t\tcase 2:\n\t\t\t\tc.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.AdditionalProtocolConfigurationOptions:\n\t\t\tc.APCO = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tc.CNOperatorSelectionEntity = i\n\t\tcase ie.PresenceReportingAreaInformation:\n\t\t\tc.PresenceReportingAreaInformation = append(c.PresenceReportingAreaInformation, i)\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.MillisecondTimeStamp:\n\t\t\tc.OriginationTimeStamp = i\n\t\tcase ie.IntegerNumber:\n\t\t\tc.MaximumWaitTime = i\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tc.WLANLocationTimeStamp = i\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.RemoteUEContext:\n\t\t\tc.RemoteUEContextConnected = append(c.RemoteUEContextConnected, i)\n\t\tcase ie.NodeIdentifier:\n\t\t\tc.TGPPAAAServerIdentifier = i\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\tc.EPCO = i\n\t\tcase ie.ServingPLMNRateControl:\n\t\t\tc.ServingPLMNRateControl = i\n\t\tcase ie.Counter:\n\t\t\tc.MOExceptionDataCounter = i\n\t\tcase ie.MappedUEUsageType:\n\t\t\tc.MappedUEUsageType = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tc.SGWUNodeName = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tc.SecondaryRATUsageDataReport = append(c.SecondaryRATUsageDataReport, i)\n\t\tcase ie.UPFunctionSelectionIndicationFlags:\n\t\t\tc.UPFunctionSelectionIndicationFlags = i\n\t\tcase ie.APNRateControlStatus:\n\t\t\tc.APNRateControlStatus = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *CreateSessionRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MSISDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MEI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ServingNetwork; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWS5S8FTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SelectionMode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PDNType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PAA; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWMI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContextsToBeCreated {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContextsToBeRemoved {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TraceInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UCI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingCharacteristics; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SignallingPriorityIndication; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UELocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UEUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBLocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CNOperatorSelectionEntity; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaInformation {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANePDGOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.OriginationTimeStamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MaximumWaitTime; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationTimeStamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.RemoteUEContextConnected {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TGPPAAAServerIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ServingPLMNRateControl; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MOExceptionDataCounter; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETCPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MappedUEUsageType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ULIForSGW; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWUNodeName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.SecondaryRATUsageDataReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UPFunctionSelectionIndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNRateControlStatus; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreateSessionRequest) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreateSessionRequest) MessageTypeName() string {\n\treturn \"Create Session Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *CreateSessionRequest) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/create-session-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreateSessionRequest into bytes.\n//\n// Deprecated: use CreateSessionRequest.Marshal instead.\nfunc (c *CreateSessionRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"CreateSessionRequest.Serialize is deprecated. use CreateSessionRequest.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreateSessionRequest into bytes given as b.\n//\n// Deprecated: use CreateSessionRequest.MarshalTo instead.\nfunc (c *CreateSessionRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"CreateSessionRequest.SerializeTo is deprecated. use CreateSessionRequest.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreateSessionRequest decodes bytes as CreateSessionRequest.\n//\n// Deprecated: use ParseCreateSessionRequest instead.\nfunc DecodeCreateSessionRequest(b []byte) (*CreateSessionRequest, error) {\n\tlog.Println(\"DecodeCreateSessionRequest is deprecated. use ParseCreateSessionRequest instead\")\n\treturn ParseCreateSessionRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as CreateSessionRequest.\n//\n// Deprecated: use CreateSessionRequest.UnmarshalBinary instead.\nfunc (c *CreateSessionRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreateSessionRequest.DecodeFromBytes is deprecated. use CreateSessionRequest.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreateSessionRequest.\n//\n// Deprecated: use CreateSessionRequest.MarshalLen instead.\nfunc (c *CreateSessionRequest) Len() int {\n\tlog.Println(\"CreateSessionRequest.Len is deprecated. use CreateSessionRequest.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/create-session-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestCreateSessionRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/FromMMEtoSGW\",\n\t\t\tStructured: message.NewCreateSessionRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewMSISDN(\"123450123456789\"),\n\t\t\t\tie.NewAccessPointName(\"some.apn.example\"),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS11MMEGTPC, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPC, 0xffffffff, \"1.1.1.2\", \"\").WithInstance(1),\n\t\t\t\tie.NewPDNType(gtpv2.PDNTypeIPv4),\n\t\t\t\tie.NewAggregateMaximumBitRate(0x11111111, 0x22222222),\n\t\t\t\tie.NewIndicationFromOctets(0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewBearerQoS(1, 2, 1, 0xff, 0x1111111111, 0x2222222222, 0x1111111111, 0x2222222222),\n\t\t\t\t),\n\t\t\t\tie.NewMobileEquipmentIdentity(\"123450123456789\"),\n\t\t\t\tie.NewServingNetwork(\"123\", \"45\"),\n\t\t\t\tie.NewPDNAddressAllocation(\"2.2.2.2\"),\n\t\t\t\tie.NewAPNRestriction(gtpv2.APNRestrictionPublic1),\n\t\t\t\tie.NewUserLocationInformationStruct(\n\t\t\t\t\tnil, nil, nil, ie.NewTAI(\"123\", \"45\", 0x0001),\n\t\t\t\t\tie.NewECGI(\"123\", \"45\", 0x00000101), nil, nil, nil,\n\t\t\t\t),\n\t\t\t\tie.NewRATType(gtpv2.RATTypeEUTRAN),\n\t\t\t\tie.NewSelectionMode(gtpv2.SelectionModeMSorNetworkProvidedAPNSubscribedVerified),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x20, 0x00, 0xed, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// MSISDN\n\t\t\t\t0x4c, 0x00, 0x08, 0x00, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9,\n\t\t\t\t// MEI\n\t\t\t\t0x4b, 0x00, 0x08, 0x00, 0x21, 0x43, 0x05, 0x21, 0x43, 0x65, 0x87, 0xf9,\n\t\t\t\t// ULI: TAI ECGI\n\t\t\t\t0x56, 0x00, 0x0d, 0x00, 0x18,\n\t\t\t\t0x21, 0xf3, 0x54, 0x00, 0x01,\n\t\t\t\t0x21, 0xf3, 0x54, 0x00, 0x00, 0x01, 0x01,\n\t\t\t\t// ServingNetwork\n\t\t\t\t0x53, 0x00, 0x03, 0x00, 0x21, 0xf3, 0x54,\n\t\t\t\t// RATType\n\t\t\t\t0x52, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t// Indication\n\t\t\t\t0x4d, 0x00, 0x07, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40,\n\t\t\t\t// F-TEID S11\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8a, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// F-TEID S5/S8\n\t\t\t\t0x57, 0x00, 0x09, 0x01, 0x87, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x02,\n\t\t\t\t// APN\n\t\t\t\t0x47, 0x00, 0x11, 0x00, 0x04, 0x73, 0x6f, 0x6d, 0x65, 0x03, 0x61, 0x70, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,\n\t\t\t\t// SelectionMode\n\t\t\t\t0x80, 0x00, 0x01, 0x00, 0x00,\n\t\t\t\t// PDNType\n\t\t\t\t0x63, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// PAA\n\t\t\t\t0x4f, 0x00, 0x05, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// APNRestriction\n\t\t\t\t0x7f, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// AMBR\n\t\t\t\t0x48, 0x00, 0x08, 0x00, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x1f, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   BearerQoS\n\t\t\t\t0x50, 0x00, 0x16, 0x00, 0x49, 0xff,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x1f, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   BearerQoS\n\t\t\t\t0x50, 0x00, 0x16, 0x00, 0x49, 0xff,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreateSessionRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/create-session-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// CreateSessionResponse is a CreateSessionResponse Header and its IEs above.\ntype CreateSessionResponse struct {\n\t*Header\n\tCause                         *ie.IE\n\tChangeReportingAction         *ie.IE\n\tCSGInformationReportingAction *ie.IE\n\tHeNBInformationReporting      *ie.IE\n\tSenderFTEIDC                  *ie.IE\n\tPGWS5S8FTEIDC                 *ie.IE\n\tPAA                           *ie.IE\n\tAPNRestriction                *ie.IE\n\tAMBR                          *ie.IE\n\tEBI                           *ie.IE\n\tPCO                           *ie.IE\n\tBearerContextsCreated         []*ie.IE\n\tBearerContextMarkedForRemoval *ie.IE\n\tRecovery                      *ie.IE\n\tChargingGatewayName           *ie.IE // = PGWNodeName\n\tChargingGatewayAddress        *ie.IE\n\tPGWFQCSID                     *ie.IE\n\tSGWFQCSID                     *ie.IE\n\tSGWLDN                        *ie.IE\n\tPGWLDN                        *ie.IE\n\tPGWBackOffTime                *ie.IE\n\tAPCO                          *ie.IE\n\tTrustedTWANIPv4Parameters     *ie.IE\n\tIndicationFlags               *ie.IE\n\tPresenceReportingAreaAction   []*ie.IE\n\tPGWNodeLoadControlInformation *ie.IE\n\tPGWAPNLoadControlInformation  *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tNBIFOMContainer               *ie.IE\n\tPDNConnectionChargingID       *ie.IE\n\tEPCO                          *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewCreateSessionResponse creates a new CreateSessionResponse.\nfunc NewCreateSessionResponse(teid, seq uint32, ies ...*ie.IE) *CreateSessionResponse {\n\tc := &CreateSessionResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeCreateSessionResponse, teid, seq, nil,\n\t\t),\n\t}\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tc.HeNBInformationReporting = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SenderFTEIDC = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWS5S8FTEIDC = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PDNAddressAllocation:\n\t\t\tc.PAA = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.AMBR = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.EBI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.BearerContextsCreated = append(c.BearerContextsCreated, i)\n\t\t\tcase 1:\n\t\t\t\tc.BearerContextMarkedForRemoval = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tc.ChargingGatewayName = i\n\t\tcase ie.IPAddress:\n\t\t\tc.ChargingGatewayAddress = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWLDN = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWLDN = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.EPCTimer:\n\t\t\tc.PGWBackOffTime = i\n\t\tcase ie.AdditionalProtocolConfigurationOptions:\n\t\t\tc.APCO = i\n\t\tcase ie.IPv4ConfigurationParameters:\n\t\t\tc.TrustedTWANIPv4Parameters = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.ChargingID:\n\t\t\tc.PDNConnectionChargingID = i\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\tc.EPCO = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes CreateSessionResponse into bytes.\nfunc (c *CreateSessionResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes CreateSessionResponse into bytes.\nfunc (c *CreateSessionResponse) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBInformationReporting; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWS5S8FTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PAA; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AMBR; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EBI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContextsCreated {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.BearerContextMarkedForRemoval; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayName; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWLDN; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWBackOffTime; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TrustedTWANIPv4Parameters; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWAPNLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PDNConnectionChargingID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseCreateSessionResponse decodes given bytes as CreateSessionResponse.\nfunc ParseCreateSessionResponse(b []byte) (*CreateSessionResponse, error) {\n\tc := &CreateSessionResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as CreateSessionResponse.\nfunc (c *CreateSessionResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tc.HeNBInformationReporting = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.SenderFTEIDC = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWS5S8FTEIDC = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PDNAddressAllocation:\n\t\t\tc.PAA = i\n\t\tcase ie.APNRestriction:\n\t\t\tc.APNRestriction = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.AMBR = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.EBI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.BearerContextsCreated = append(c.BearerContextsCreated, i)\n\t\t\tcase 1:\n\t\t\t\tc.BearerContextMarkedForRemoval = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tc.ChargingGatewayName = i\n\t\tcase ie.IPAddress:\n\t\t\tc.ChargingGatewayAddress = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWLDN = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWLDN = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.EPCTimer:\n\t\t\tc.PGWBackOffTime = i\n\t\tcase ie.AdditionalProtocolConfigurationOptions:\n\t\t\tc.APCO = i\n\t\tcase ie.IPv4ConfigurationParameters:\n\t\t\tc.TrustedTWANIPv4Parameters = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.ChargingID:\n\t\t\tc.PDNConnectionChargingID = i\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\tc.EPCO = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *CreateSessionResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBInformationReporting; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWS5S8FTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PAA; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNRestriction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContextsCreated {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.BearerContextMarkedForRemoval; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWBackOffTime; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TrustedTWANIPv4Parameters; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWAPNLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PDNConnectionChargingID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *CreateSessionResponse) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *CreateSessionResponse) MessageTypeName() string {\n\treturn \"Create Session Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *CreateSessionResponse) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/create-session-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes CreateSessionResponse into bytes.\n//\n// Deprecated: use CreateSessionResponse.Marshal instead.\nfunc (c *CreateSessionResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"CreateSessionResponse.Serialize is deprecated. use CreateSessionResponse.Marshal instead\")\n\treturn c.Marshal()\n}\n\n// SerializeTo serializes CreateSessionResponse into bytes given as b.\n//\n// Deprecated: use CreateSessionResponse.MarshalTo instead.\nfunc (c *CreateSessionResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"CreateSessionResponse.SerializeTo is deprecated. use CreateSessionResponse.MarshalTo instead\")\n\treturn c.MarshalTo(b)\n}\n\n// DecodeCreateSessionResponse decodes bytes as CreateSessionResponse.\n//\n// Deprecated: use ParseCreateSessionResponse instead.\nfunc DecodeCreateSessionResponse(b []byte) (*CreateSessionResponse, error) {\n\tlog.Println(\"DecodeCreateSessionResponse is deprecated. use ParseCreateSessionResponse instead\")\n\treturn ParseCreateSessionResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as CreateSessionResponse.\n//\n// Deprecated: use CreateSessionResponse.UnmarshalBinary instead.\nfunc (c *CreateSessionResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"CreateSessionResponse.DecodeFromBytes is deprecated. use CreateSessionResponse.UnmarshalBinary instead\")\n\treturn c.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of CreateSessionResponse.\n//\n// Deprecated: use CreateSessionResponse.MarshalLen instead.\nfunc (c *CreateSessionResponse) Len() int {\n\tlog.Println(\"CreateSessionResponse.Len is deprecated. use CreateSessionResponse.MarshalLen instead\")\n\treturn c.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/create-session-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestCreateSessionResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/FromSGWtoMME\",\n\t\t\tStructured: message.NewCreateSessionResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS11S4SGWGTPC, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPC, 0xffffffff, \"1.1.1.2\", \"\").WithInstance(1),\n\t\t\t\tie.NewPDNAddressAllocation(\"2.2.2.2\"),\n\t\t\t\tie.NewAPNRestriction(gtpv2.APNRestrictionPublic1),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPU, 0xffffffff, \"1.1.1.2\", \"\").WithInstance(1),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPU, 0xffffffff, \"1.1.1.2\", \"\").WithInstance(1),\n\t\t\t\t),\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.2\", 1),\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.3\", 1).WithInstance(1),\n\t\t\t\tie.NewChargingID(1),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x21, 0x00, 0xa6, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8b, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t\t// F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x01, 0x87, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x02,\n\t\t\t\t// PAA\n\t\t\t\t0x4f, 0x00, 0x05, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02,\n\t\t\t\t// APNRestriction\n\t\t\t\t0x7f, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x25, 0x00,\n\t\t\t\t//   Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t\t//   F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x01, 0x85, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x02,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x25, 0x00,\n\t\t\t\t//   Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t\t//   F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x01, 0x85, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x02,\n\t\t\t\t// FQ-CSID\n\t\t\t\t0x84, 0x00, 0x07, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01,\n\t\t\t\t0x84, 0x00, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x01,\n\t\t\t\t// ChargingID\n\t\t\t\t0x5e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseCreateSessionResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-command.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// DeleteBearerCommand is a DeleteBearerCommand Header and its IEs above.\ntype DeleteBearerCommand struct {\n\t*Header\n\tBearerContexts                    []*ie.IE\n\tULI                               *ie.IE\n\tULITimestamp                      *ie.IE\n\tUETimeZone                        *ie.IE\n\tMMESGSNOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation     *ie.IE\n\tSenderFTEIDC                      *ie.IE\n\tSecondaryRATDataUsageReport       []*ie.IE\n\tPrivateExtension                  *ie.IE\n\tAdditionalIEs                     []*ie.IE\n}\n\n// NewDeleteBearerCommand creates a new DeleteBearerCommand.\nfunc NewDeleteBearerCommand(teid, seq uint32, ies ...*ie.IE) *DeleteBearerCommand {\n\td := &DeleteBearerCommand{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeleteBearerCommand, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.BearerContext:\n\t\t\td.BearerContexts = append(d.BearerContexts, i)\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.UETimeZone:\n\t\t\td.UETimeZone = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\td.SenderFTEIDC = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\td.SecondaryRATDataUsageReport = append(d.SecondaryRATDataUsageReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DeleteBearerCommand into bytes.\nfunc (d *DeleteBearerCommand) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeleteBearerCommand into bytes.\nfunc (d *DeleteBearerCommand) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range d.BearerContexts {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MMESGSNOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.SecondaryRATDataUsageReport {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeleteBearerCommand decodes given bytes as DeleteBearerCommand.\nfunc ParseDeleteBearerCommand(b []byte) (*DeleteBearerCommand, error) {\n\td := &DeleteBearerCommand{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeleteBearerCommand.\nfunc (d *DeleteBearerCommand) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.BearerContext:\n\t\t\td.BearerContexts = append(d.BearerContexts, i)\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.UETimeZone:\n\t\t\td.UETimeZone = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\td.SenderFTEIDC = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\td.SecondaryRATDataUsageReport = append(d.SecondaryRATDataUsageReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DeleteBearerCommand) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\tfor _, ie := range d.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MMESGSNOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.SecondaryRATDataUsageReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeleteBearerCommand) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeleteBearerCommand) MessageTypeName() string {\n\treturn \"Delete Bearer Command\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DeleteBearerCommand) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-command_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeleteBearerCommand(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeleteBearerCommand(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewBearerContext(ie.NewEPSBearerID(5), ie.NewDelayValue(500*time.Millisecond), ie.NewDelayValue(100*time.Millisecond)),\n\t\t\t\tie.NewBearerContext(ie.NewEPSBearerID(6), ie.NewDelayValue(500*time.Millisecond), ie.NewDelayValue(100*time.Millisecond)),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x42, 0x00, 0x2e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// BearerContexts 1\n\t\t\t\t0x5d, 0x00, 0x0f, 0x00,\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x0a,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x02,\n\t\t\t\t// BearerContexts 2\n\t\t\t\t0x5d, 0x00, 0x0f, 0x00,\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x0a,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x02,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeleteBearerCommand(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-failure-indication.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// DeleteBearerFailureIndication is a DeleteBearerFailureIndication Header and its IEs above.\ntype DeleteBearerFailureIndication struct {\n\t*Header\n\tCause                         *ie.IE\n\tBearerContexts                []*ie.IE\n\tRecovery                      *ie.IE\n\tIndicationFlags               *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewDeleteBearerFailureIndication creates a new DeleteBearerFailureIndication.\nfunc NewDeleteBearerFailureIndication(teid, seq uint32, ies ...*ie.IE) *DeleteBearerFailureIndication {\n\td := &DeleteBearerFailureIndication{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeleteBearerFailureIndication, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\td.BearerContexts = append(d.BearerContexts, i)\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DeleteBearerFailureIndication into bytes.\nfunc (d *DeleteBearerFailureIndication) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeleteBearerFailureIndication into bytes.\nfunc (d *DeleteBearerFailureIndication) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.BearerContexts {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeleteBearerFailureIndication decodes given bytes as DeleteBearerFailureIndication.\nfunc ParseDeleteBearerFailureIndication(b []byte) (*DeleteBearerFailureIndication, error) {\n\td := &DeleteBearerFailureIndication{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeleteBearerFailureIndication.\nfunc (d *DeleteBearerFailureIndication) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\td.BearerContexts = append(d.BearerContexts, i)\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DeleteBearerFailureIndication) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeleteBearerFailureIndication) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeleteBearerFailureIndication) MessageTypeName() string {\n\treturn \"Delete Bearer Failure Indication\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DeleteBearerFailureIndication) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-failure-indication_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeleteBearerFailureIndication(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeleteBearerFailureIndication(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(ie.NewEPSBearerID(5), ie.NewDelayValue(500*time.Millisecond), ie.NewDelayValue(100*time.Millisecond)),\n\t\t\t\tie.NewBearerContext(ie.NewEPSBearerID(6), ie.NewDelayValue(500*time.Millisecond), ie.NewDelayValue(100*time.Millisecond)),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x43, 0x00, 0x34, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// BearerContexts 1\n\t\t\t\t0x5d, 0x00, 0x0f, 0x00,\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x0a,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x02,\n\t\t\t\t// BearerContexts 2\n\t\t\t\t0x5d, 0x00, 0x0f, 0x00,\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x0a,\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x02,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeleteBearerFailureIndication(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DeleteBearerRequest is a DeleteBearerRequest Header and its IEs above.\ntype DeleteBearerRequest struct {\n\t*Header\n\tLinkedEBI                     *ie.IE\n\tEBIs                          []*ie.IE\n\tFailedBearerContext           *ie.IE\n\tPTI                           *ie.IE\n\tPCO                           *ie.IE\n\tPGWFQCSID                     *ie.IE\n\tSGWFQCSID                     *ie.IE\n\tCause                         *ie.IE\n\tIndicationFlags               *ie.IE\n\tPGWNodeLoadControlInformation *ie.IE\n\tPGWAPNLoadControlInformation  *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tNBIFOMContainer               *ie.IE\n\tAPNRateControlStatus          *ie.IE\n\tEPCO                          *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewDeleteBearerRequest creates a new DeleteBearerRequest.\nfunc NewDeleteBearerRequest(teid, seq uint32, ies ...*ie.IE) *DeleteBearerRequest {\n\td := &DeleteBearerRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeleteBearerRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.EPSBearerID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.LinkedEBI = i\n\t\t\tcase 1:\n\t\t\t\td.EBIs = append(d.EBIs, i)\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.BearerContext:\n\t\t\td.FailedBearerContext = i\n\t\tcase ie.ProcedureTransactionID:\n\t\t\td.PTI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\td.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\td.NBIFOMContainer = i\n\t\tcase ie.APNRateControlStatus:\n\t\t\td.APNRateControlStatus = i\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\td.EPCO = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DeleteBearerRequest into bytes.\nfunc (d *DeleteBearerRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeleteBearerRequest into bytes.\nfunc (d *DeleteBearerRequest) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\n\tif ie := d.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.EBIs {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.FailedBearerContext; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PTI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWAPNLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.APNRateControlStatus; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.EPCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeleteBearerRequest decodes given bytes as DeleteBearerRequest.\nfunc ParseDeleteBearerRequest(b []byte) (*DeleteBearerRequest, error) {\n\td := &DeleteBearerRequest{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeleteBearerRequest.\nfunc (d *DeleteBearerRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.EPSBearerID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.LinkedEBI = i\n\t\t\tcase 1:\n\t\t\t\td.EBIs = append(d.EBIs, i)\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.BearerContext:\n\t\t\td.FailedBearerContext = i\n\t\tcase ie.ProcedureTransactionID:\n\t\t\td.PTI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\td.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\td.NBIFOMContainer = i\n\t\tcase ie.APNRateControlStatus:\n\t\t\td.APNRateControlStatus = i\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\td.EPCO = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DeleteBearerRequest) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.EBIs {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.FailedBearerContext; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PTI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWAPNLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.APNRateControlStatus; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.EPCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeleteBearerRequest) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeleteBearerRequest) MessageTypeName() string {\n\treturn \"Delete Bearer Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DeleteBearerRequest) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeleteBearerRequest into bytes.\n//\n// Deprecated: use DeleteBearerRequest.Marshal instead.\nfunc (d *DeleteBearerRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"DeleteBearerRequest.Serialize is deprecated. use DeleteBearerRequest.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeleteBearerRequest into bytes given as b.\n//\n// Deprecated: use DeleteBearerRequest.MarshalTo instead.\nfunc (d *DeleteBearerRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"DeleteBearerRequest.SerializeTo is deprecated. use DeleteBearerRequest.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeleteBearerRequest decodes bytes as DeleteBearerRequest.\n//\n// Deprecated: use ParseDeleteBearerRequest instead.\nfunc DecodeDeleteBearerRequest(b []byte) (*DeleteBearerRequest, error) {\n\tlog.Println(\"DecodeDeleteBearerRequest is deprecated. use ParseDeleteBearerRequest instead\")\n\treturn ParseDeleteBearerRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as DeleteBearerRequest.\n//\n// Deprecated: use DeleteBearerRequest.UnmarshalBinary instead.\nfunc (d *DeleteBearerRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeleteBearerRequest.DecodeFromBytes is deprecated. use DeleteBearerRequest.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeleteBearerRequest.\n//\n// Deprecated: use DeleteBearerRequest.MarshalLen instead.\nfunc (d *DeleteBearerRequest) Len() int {\n\tlog.Println(\"DeleteBearerRequest.Len is deprecated. use DeleteBearerRequest.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeleteBearerRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeleteBearerRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewEPSBearerID(5),\n\t\t\t\tie.NewCause(gtpv2.CauseISRDeactivation, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x63, 0x00, 0x13, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x05, 0x00,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"EBIs\",\n\t\t\tStructured: message.NewDeleteBearerRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewEPSBearerID(5).WithInstance(1),\n\t\t\t\tie.NewEPSBearerID(6).WithInstance(1),\n\t\t\t\tie.NewCause(gtpv2.CauseISRDeactivation, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x63, 0x00, 0x18, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// EBIs 1\n\t\t\t\t0x49, 0x00, 0x01, 0x01, 0x05,\n\t\t\t\t// EBIs 2\n\t\t\t\t0x49, 0x00, 0x01, 0x01, 0x06,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x05, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeleteBearerRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DeleteBearerResponse is a DeleteBearerResponse Header and its IEs above.\ntype DeleteBearerResponse struct {\n\t*Header\n\tCause                              *ie.IE\n\tLinkedEBI                          *ie.IE\n\tBearerContexts                     []*ie.IE\n\tRecovery                           *ie.IE\n\tMMEFQCSID                          *ie.IE\n\tSGWFQCSID                          *ie.IE\n\tEPDGFQCSID                         *ie.IE\n\tTWANFQCSID                         *ie.IE\n\tPCO                                *ie.IE\n\tUETimeZone                         *ie.IE\n\tULI                                *ie.IE\n\tULITimestamp                       *ie.IE\n\tTWANIdentifier                     *ie.IE\n\tTWANIdentifierTimestamp            *ie.IE\n\tMMEOverloadControlInformation      *ie.IE\n\tSGWOverloadControlInformation      *ie.IE\n\tMMESGSNIdentifier                  *ie.IE\n\tTWANePDGOverloadControlInformation *ie.IE\n\tWLANLocationInformation            *ie.IE\n\tWLANLocationTimestamp              *ie.IE\n\tUELocalIPAddress                   *ie.IE\n\tUEUDPPort                          *ie.IE\n\tNBIFOMContainer                    *ie.IE\n\tUETCPPort                          *ie.IE\n\tSecondaryRATUsageDataReport        []*ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewDeleteBearerResponse creates a new DeleteBearerResponse.\nfunc NewDeleteBearerResponse(teid, seq uint32, ies ...*ie.IE) *DeleteBearerResponse {\n\td := &DeleteBearerResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeleteBearerResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.EPSBearerID:\n\t\t\td.LinkedEBI = i\n\t\tcase ie.BearerContext:\n\t\t\td.BearerContexts = append(d.BearerContexts, i)\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\td.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\td.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\td.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.UETimeZone:\n\t\t\td.UETimeZone = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifierTimestamp = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationTimestamp = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMEOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMESGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\td.UELocalIPAddress = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\td.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\td.NBIFOMContainer = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\td.SecondaryRATUsageDataReport = append(d.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DeleteBearerResponse into bytes.\nfunc (d *DeleteBearerResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeleteBearerResponse into bytes.\nfunc (d *DeleteBearerResponse) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.BearerContexts {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.EPDGFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifierTimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MMEOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MMESGSNIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANePDGOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationTimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UELocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UEUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UETCPPort; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.SecondaryRATUsageDataReport {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeleteBearerResponse decodes given bytes as DeleteBearerResponse.\nfunc ParseDeleteBearerResponse(b []byte) (*DeleteBearerResponse, error) {\n\td := &DeleteBearerResponse{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeleteBearerResponse.\nfunc (d *DeleteBearerResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.EPSBearerID:\n\t\t\td.LinkedEBI = i\n\t\tcase ie.BearerContext:\n\t\t\td.BearerContexts = append(d.BearerContexts, i)\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\td.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\td.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\td.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.UETimeZone:\n\t\t\td.UETimeZone = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifierTimestamp = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationTimestamp = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMEOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMESGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\td.UELocalIPAddress = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\td.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\td.NBIFOMContainer = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\td.SecondaryRATUsageDataReport = append(d.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DeleteBearerResponse) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.EPDGFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifierTimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MMEOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MMESGSNIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANePDGOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationTimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UELocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UEUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UETCPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range d.SecondaryRATUsageDataReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeleteBearerResponse) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeleteBearerResponse) MessageTypeName() string {\n\treturn \"Delete Bearer Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DeleteBearerResponse) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeleteBearerResponse into bytes.\n//\n// Deprecated: use DeleteBearerResponse.Marshal instead.\nfunc (d *DeleteBearerResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"DeleteBearerResponse.Serialize is deprecated. use DeleteBearerResponse.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeleteBearerResponse into bytes given as b.\n//\n// Deprecated: use DeleteBearerResponse.MarshalTo instead.\nfunc (d *DeleteBearerResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"DeleteBearerResponse.SerializeTo is deprecated. use DeleteBearerResponse.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeleteBearerResponse decodes bytes as DeleteBearerResponse.\n//\n// Deprecated: use ParseDeleteBearerResponse instead.\nfunc DecodeDeleteBearerResponse(b []byte) (*DeleteBearerResponse, error) {\n\tlog.Println(\"DecodeDeleteBearerResponse is deprecated. use ParseDeleteBearerResponse instead\")\n\treturn ParseDeleteBearerResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as DeleteBearerResponse.\n//\n// Deprecated: use DeleteBearerResponse.UnmarshalBinary instead.\nfunc (d *DeleteBearerResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeleteBearerResponse.DecodeFromBytes is deprecated. use DeleteBearerResponse.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeleteBearerResponse.\n//\n// Deprecated: use DeleteBearerResponse.MarshalLen instead.\nfunc (d *DeleteBearerResponse) Len() int {\n\tlog.Println(\"DeleteBearerResponse.Len is deprecated. use DeleteBearerResponse.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-bearer-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeleteBearerResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/CauseOnly\",\n\t\t\tStructured: message.NewDeleteBearerResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x64, 0x00, 0x3a, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeleteBearerResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-pdn-connection-set-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DeletePDNConnectionSetRequest is a DeletePDNConnectionSetRequest Header and its IEs above.\ntype DeletePDNConnectionSetRequest struct {\n\t*Header\n\tMMEFQCSID        *ie.IE\n\tSGWFQCSID        *ie.IE\n\tPGWFQCSID        *ie.IE\n\tEPDGFQCSID       *ie.IE\n\tTWANFQCSID       *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDeletePDNConnectionSetRequest creates a new DeletePDNConnectionSetRequest.\nfunc NewDeletePDNConnectionSetRequest(teid, seq uint32, ies ...*ie.IE) *DeletePDNConnectionSetRequest {\n\tm := &DeletePDNConnectionSetRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeletePDNConnectionSetRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tm.PGWFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tm.EPDGFQCSID = i\n\t\t\tcase 4:\n\t\t\t\tm.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes DeletePDNConnectionSetRequest into bytes.\nfunc (m *DeletePDNConnectionSetRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeletePDNConnectionSetRequest into bytes.\nfunc (m *DeletePDNConnectionSetRequest) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.EPDGFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.TWANFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseDeletePDNConnectionSetRequest decodes given bytes as DeletePDNConnectionSetRequest.\nfunc ParseDeletePDNConnectionSetRequest(b []byte) (*DeletePDNConnectionSetRequest, error) {\n\tm := &DeletePDNConnectionSetRequest{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeletePDNConnectionSetRequest.\nfunc (m *DeletePDNConnectionSetRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tm.PGWFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tm.EPDGFQCSID = i\n\t\t\tcase 4:\n\t\t\t\tm.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *DeletePDNConnectionSetRequest) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.EPDGFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.TWANFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *DeletePDNConnectionSetRequest) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *DeletePDNConnectionSetRequest) MessageTypeName() string {\n\treturn \"Delete PDN Connection Set Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *DeletePDNConnectionSetRequest) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-pdn-connection-set-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeletePDNConnectionSetRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeletePDNConnectionSetRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1),\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1).WithInstance(4),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x65, 0x00, 0x1e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// MME-FQ-CSID\n\t\t\t\t0x84, 0x00, 0x07, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,\n\t\t\t\t// TWAN-FQ-CSID\n\t\t\t\t0x84, 0x00, 0x07, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeletePDNConnectionSetRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-pdn-connection-set-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DeletePDNConnectionSetResponse is a DeletePDNConnectionSetResponse Header and its IEs above.\ntype DeletePDNConnectionSetResponse struct {\n\t*Header\n\tCause            *ie.IE\n\tRecovery         *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDeletePDNConnectionSetResponse creates a new DeletePDNConnectionSetResponse.\nfunc NewDeletePDNConnectionSetResponse(teid, seq uint32, ies ...*ie.IE) *DeletePDNConnectionSetResponse {\n\tm := &DeletePDNConnectionSetResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeletePDNConnectionSetResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal returns the byte sequence generated from a DeletePDNConnectionSetResponse.\nfunc (m *DeletePDNConnectionSetResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (m *DeletePDNConnectionSetResponse) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseDeletePDNConnectionSetResponse decodes a given byte sequence as a DeletePDNConnectionSetResponse.\nfunc ParseDeletePDNConnectionSetResponse(b []byte) (*DeletePDNConnectionSetResponse, error) {\n\tm := &DeletePDNConnectionSetResponse{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given byte sequence as DeletePDNConnectionSetResponse.\nfunc (m *DeletePDNConnectionSetResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (m *DeletePDNConnectionSetResponse) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *DeletePDNConnectionSetResponse) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *DeletePDNConnectionSetResponse) MessageTypeName() string {\n\treturn \"Delete PDN Connection Set Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *DeletePDNConnectionSetResponse) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-pdn-connection-set-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeletePDNConnectionSetResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDeletePDNConnectionSetResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewRecovery(0xff),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x66, 0x00, 0x13, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// Recovery\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0xff,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeletePDNConnectionSetResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-session-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DeleteSessionRequest is a DeleteSessionRequest Header and its IEs above.\ntype DeleteSessionRequest struct {\n\t*Header\n\tCause                             *ie.IE\n\tLinkedEBI                         *ie.IE\n\tULI                               *ie.IE\n\tIndicationFlags                   *ie.IE\n\tPCO                               *ie.IE\n\tOriginatingNode                   *ie.IE\n\tSenderFTEIDC                      *ie.IE\n\tUETimeZone                        *ie.IE\n\tULITimestamp                      *ie.IE\n\tRANNASReleaseCause                *ie.IE\n\tTWANIdentifier                    *ie.IE\n\tTWANIdentifierTimestamp           *ie.IE\n\tMMESGSNOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformaion      *ie.IE\n\tTWANePDGOverloadControlInformaion *ie.IE\n\tWLANLocationInformation           *ie.IE\n\tWLANLocationTimeStamp             *ie.IE\n\tUELocalIPAddress                  *ie.IE\n\tUEUDPPort                         *ie.IE\n\tEPCO                              *ie.IE\n\tUETCPPort                         *ie.IE\n\tSecondaryRATUsageDataReport       *ie.IE\n\tPrivateExtension                  *ie.IE\n\tAdditionalIEs                     []*ie.IE\n}\n\n// NewDeleteSessionRequest creates a new DeleteSessionRequest.\nfunc NewDeleteSessionRequest(teid, seq uint32, ies ...*ie.IE) *DeleteSessionRequest {\n\td := &DeleteSessionRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeleteSessionRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.EPSBearerID:\n\t\t\td.LinkedEBI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.NodeType:\n\t\t\td.OriginatingNode = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\td.SenderFTEIDC = i\n\t\tcase ie.UETimeZone:\n\t\t\td.UETimeZone = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.RANNASCause:\n\t\t\td.RANNASReleaseCause = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifierTimestamp = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationTimeStamp = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformaion = i\n\t\t\tcase 2:\n\t\t\t\td.TWANePDGOverloadControlInformaion = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.IPAddress:\n\t\t\td.UELocalIPAddress = i\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\td.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\td.EPCO = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\td.SecondaryRATUsageDataReport = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DeleteSessionRequest into bytes.\nfunc (d *DeleteSessionRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeleteSessionRequest into bytes.\nfunc (d *DeleteSessionRequest) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.OriginatingNode; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.RANNASReleaseCause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifierTimestamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.MMESGSNOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformaion; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.TWANePDGOverloadControlInformaion; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationTimeStamp; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UELocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UEUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.EPCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.UETCPPort; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SecondaryRATUsageDataReport; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeleteSessionRequest decodes given bytes as DeleteSessionRequest.\nfunc ParseDeleteSessionRequest(b []byte) (*DeleteSessionRequest, error) {\n\td := &DeleteSessionRequest{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeleteSessionRequest.\nfunc (d *DeleteSessionRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.EPSBearerID:\n\t\t\td.LinkedEBI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\td.ULI = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.NodeType:\n\t\t\td.OriginatingNode = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\td.SenderFTEIDC = i\n\t\tcase ie.UETimeZone:\n\t\t\td.UETimeZone = i\n\t\tcase ie.ULITimestamp:\n\t\t\td.ULITimestamp = i\n\t\tcase ie.RANNASCause:\n\t\t\td.RANNASReleaseCause = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.TWANIdentifierTimestamp = i\n\t\t\tcase 1:\n\t\t\t\td.WLANLocationTimeStamp = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\td.SGWOverloadControlInformaion = i\n\t\t\tcase 2:\n\t\t\t\td.TWANePDGOverloadControlInformaion = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.IPAddress:\n\t\t\td.UELocalIPAddress = i\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\td.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\td.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\td.EPCO = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\td.SecondaryRATUsageDataReport = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DeleteSessionRequest) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.OriginatingNode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.ULITimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.RANNASReleaseCause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANIdentifierTimestamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.MMESGSNOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformaion; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.TWANePDGOverloadControlInformaion; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.WLANLocationTimeStamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UELocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UEUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.EPCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.UETCPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SecondaryRATUsageDataReport; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeleteSessionRequest) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeleteSessionRequest) MessageTypeName() string {\n\treturn \"Delete Session Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DeleteSessionRequest) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-session-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeleteSessionRequest into bytes.\n//\n// Deprecated: use DeleteSessionRequest.Marshal instead.\nfunc (d *DeleteSessionRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"DeleteSessionRequest.Serialize is deprecated. use DeleteSessionRequest.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeleteSessionRequest into bytes given as b.\n//\n// Deprecated: use DeleteSessionRequest.MarshalTo instead.\nfunc (d *DeleteSessionRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"DeleteSessionRequest.SerializeTo is deprecated. use DeleteSessionRequest.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeleteSessionRequest decodes bytes as DeleteSessionRequest.\n//\n// Deprecated: use ParseDeleteSessionRequest instead.\nfunc DecodeDeleteSessionRequest(b []byte) (*DeleteSessionRequest, error) {\n\tlog.Println(\"DecodeDeleteSessionRequest is deprecated. use ParseDeleteSessionRequest instead\")\n\treturn ParseDeleteSessionRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as DeleteSessionRequest.\n//\n// Deprecated: use DeleteSessionRequest.UnmarshalBinary instead.\nfunc (d *DeleteSessionRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeleteSessionRequest.DecodeFromBytes is deprecated. use DeleteSessionRequest.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeleteSessionRequest.\n//\n// Deprecated: use DeleteSessionRequest.MarshalLen instead.\nfunc (d *DeleteSessionRequest) Len() int {\n\tlog.Println(\"DeleteSessionRequest.Len is deprecated. use DeleteSessionRequest.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-session-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeleteSessionRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/FromMMEtoSGW\",\n\t\t\tStructured: message.NewDeleteSessionRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewEPSBearerID(5),\n\t\t\t\tie.NewUserLocationInformationStruct(\n\t\t\t\t\tnil, nil, nil, ie.NewTAI(\"123\", \"45\", 0x0001),\n\t\t\t\t\tie.NewECGI(\"123\", \"45\", 0x00000101), nil, nil, nil,\n\t\t\t\t),\n\t\t\t\tie.NewIndicationFromOctets(0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40),\n\t\t\t\tie.NewULITimestamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x24, 0x00, 0x31, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// ULI: TAI ECGI\n\t\t\t\t0x56, 0x00, 0x0d, 0x00, 0x18,\n\t\t\t\t0x21, 0xf3, 0x54, 0x00, 0x01,\n\t\t\t\t0x21, 0xf3, 0x54, 0x00, 0x00, 0x01, 0x01,\n\t\t\t\t// Indication\n\t\t\t\t0x4d, 0x00, 0x07, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40,\n\t\t\t\t// ULITimestamp\n\t\t\t\t0xaa, 0x00, 0x04, 0x00, 0xdf, 0xd5, 0x2c, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeleteSessionRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/delete-session-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DeleteSessionResponse is a DeleteSessionResponse Header and its IEs above.\ntype DeleteSessionResponse struct {\n\t*Header\n\tCause                         *ie.IE\n\tRecovery                      *ie.IE\n\tPCO                           *ie.IE\n\tIndicationFlags               *ie.IE\n\tPGWNodeLoadControlInformation *ie.IE\n\tPGWAPNLoadControlInformation  *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tEPCO                          *ie.IE\n\tAPNRateControlStatus          *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewDeleteSessionResponse creates a new DeleteSessionResponse.\nfunc NewDeleteSessionResponse(teid, seq uint32, ies ...*ie.IE) *DeleteSessionResponse {\n\td := &DeleteSessionResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDeleteSessionResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\td.PGWNodeLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.PGWAPNLoadControlInformation = i\n\t\t\tcase 3:\n\t\t\t\td.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\td.PGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\td.EPCO = i\n\t\tcase ie.APNRateControlStatus:\n\t\t\td.APNRateControlStatus = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DeleteSessionResponse into bytes.\nfunc (d *DeleteSessionResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DeleteSessionResponse into bytes.\nfunc (d *DeleteSessionResponse) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWAPNLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.EPCO; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.APNRateControlStatus; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDeleteSessionResponse decodes given bytes as DeleteSessionResponse.\nfunc ParseDeleteSessionResponse(b []byte) (*DeleteSessionResponse, error) {\n\td := &DeleteSessionResponse{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DeleteSessionResponse.\nfunc (d *DeleteSessionResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\td.PCO = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\td.PGWNodeLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.PGWAPNLoadControlInformation = i\n\t\t\tcase 3:\n\t\t\t\td.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\td.PGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\td.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ExtendedProtocolConfigurationOptions:\n\t\t\td.EPCO = i\n\t\tcase ie.APNRateControlStatus:\n\t\t\td.APNRateControlStatus = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DeleteSessionResponse) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWAPNLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.EPCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.APNRateControlStatus; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DeleteSessionResponse) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DeleteSessionResponse) MessageTypeName() string {\n\treturn \"Delete Session Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DeleteSessionResponse) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-session-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes DeleteSessionResponse into bytes.\n//\n// Deprecated: use DeleteSessionResponse.Marshal instead.\nfunc (d *DeleteSessionResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"DeleteSessionResponse.Serialize is deprecated. use DeleteSessionResponse.Marshal instead\")\n\treturn d.Marshal()\n}\n\n// SerializeTo serializes DeleteSessionResponse into bytes given as b.\n//\n// Deprecated: use DeleteSessionResponse.MarshalTo instead.\nfunc (d *DeleteSessionResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"DeleteSessionResponse.SerializeTo is deprecated. use DeleteSessionResponse.MarshalTo instead\")\n\treturn d.MarshalTo(b)\n}\n\n// DecodeDeleteSessionResponse decodes bytes as DeleteSessionResponse.\n//\n// Deprecated: use ParseDeleteSessionResponse instead.\nfunc DecodeDeleteSessionResponse(b []byte) (*DeleteSessionResponse, error) {\n\tlog.Println(\"DecodeDeleteSessionResponse is deprecated. use ParseDeleteSessionResponse instead\")\n\treturn ParseDeleteSessionResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as DeleteSessionResponse.\n//\n// Deprecated: use DeleteSessionResponse.UnmarshalBinary instead.\nfunc (d *DeleteSessionResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"DeleteSessionResponse.DecodeFromBytes is deprecated. use DeleteSessionResponse.UnmarshalBinary instead\")\n\treturn d.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of DeleteSessionResponse.\n//\n// Deprecated: use DeleteSessionResponse.MarshalLen instead.\nfunc (d *DeleteSessionResponse) Len() int {\n\tlog.Println(\"DeleteSessionResponse.Len is deprecated. use DeleteSessionResponse.MarshalLen instead\")\n\treturn d.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/delete-session-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDeleteSessionResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/CauseOnly\",\n\t\t\tStructured: message.NewDeleteSessionResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x25, 0x00, 0x0e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDeleteSessionResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/detach-acknowledge.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DetachAcknowledge is a DetachAcknowledge Header and its IEs above.\ntype DetachAcknowledge struct {\n\t*Header\n\tCause            *ie.IE\n\tRecovery         *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDetachAcknowledge creates a new DetachAcknowledge.\nfunc NewDetachAcknowledge(teid, seq uint32, ies ...*ie.IE) *DetachAcknowledge {\n\tm := &DetachAcknowledge{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDetachAcknowledge, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal returns the byte sequence generated from a DetachAcknowledge.\nfunc (m *DetachAcknowledge) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (m *DetachAcknowledge) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseDetachAcknowledge decodes a given byte sequence as a DetachAcknowledge.\nfunc ParseDetachAcknowledge(b []byte) (*DetachAcknowledge, error) {\n\tm := &DetachAcknowledge{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given byte sequence as DetachAcknowledge.\nfunc (m *DetachAcknowledge) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (m *DetachAcknowledge) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *DetachAcknowledge) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *DetachAcknowledge) MessageTypeName() string {\n\treturn \"Detach Acknowledge\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *DetachAcknowledge) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/detach-acknowledge_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDetachAcknowledge(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDetachAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewRecovery(0xff),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x96, 0x00, 0x13, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// Recovery\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0xff,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDetachAcknowledge(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/detach-notification.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DetachNotification is a DetachNotification Header and its IEs above.\ntype DetachNotification struct {\n\t*Header\n\tCause            *ie.IE\n\tDetachType       *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDetachNotification creates a new DetachNotification.\nfunc NewDetachNotification(teid, seq uint32, ies ...*ie.IE) *DetachNotification {\n\tm := &DetachNotification{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDetachNotification, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.DetachType:\n\t\t\tm.DetachType = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes DetachNotification into bytes.\nfunc (m *DetachNotification) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DetachNotification into bytes.\nfunc (m *DetachNotification) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.DetachType; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseDetachNotification decodes given bytes as DetachNotification.\nfunc ParseDetachNotification(b []byte) (*DetachNotification, error) {\n\tm := &DetachNotification{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as DetachNotification.\nfunc (m *DetachNotification) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.DetachType:\n\t\t\tm.DetachType = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *DetachNotification) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.DetachType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *DetachNotification) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *DetachNotification) MessageTypeName() string {\n\treturn \"Detach Notification\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *DetachNotification) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/detach-notification_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDetachNotification(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDetachNotification(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewDetachType(gtpv2.DetachTypePS),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x95, 0x00, 0x13, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// Detach Type\n\t\t\t\t0x96, 0x00, 0x01, 0x00, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDetachNotification(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/downlink-data-notification-ack.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DownlinkDataNotificationAcknowledge is a DownlinkDataNotificationAcknowledge Header and its IEs above.\ntype DownlinkDataNotificationAcknowledge struct {\n\t*Header\n\tCause                           *ie.IE\n\tDataNotificationDelay           *ie.IE\n\tRecovery                        *ie.IE\n\tDLLowPriorityTrafficThrottling  *ie.IE\n\tIMSI                            *ie.IE\n\tDLBufferingDuration             *ie.IE\n\tDLBufferingSuggestedPacketCount *ie.IE\n\tPrivateExtension                *ie.IE\n\tAdditionalIEs                   []*ie.IE\n}\n\n// NewDownlinkDataNotificationAcknowledge creates a new DownlinkDataNotificationAcknowledge.\nfunc NewDownlinkDataNotificationAcknowledge(teid, seq uint32, ies ...*ie.IE) *DownlinkDataNotificationAcknowledge {\n\td := &DownlinkDataNotificationAcknowledge{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDownlinkDataNotificationAcknowledge, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.DelayValue:\n\t\t\td.DataNotificationDelay = i\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.Throttling:\n\t\t\td.DLLowPriorityTrafficThrottling = i\n\t\tcase ie.IMSI:\n\t\t\td.IMSI = i\n\t\tcase ie.EPCTimer:\n\t\t\td.DLBufferingDuration = i\n\t\tcase ie.IntegerNumber:\n\t\t\td.DLBufferingSuggestedPacketCount = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DownlinkDataNotificationAcknowledge into bytes.\nfunc (d *DownlinkDataNotificationAcknowledge) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DownlinkDataNotificationAcknowledge into bytes.\nfunc (d *DownlinkDataNotificationAcknowledge) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.DataNotificationDelay; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.DLLowPriorityTrafficThrottling; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.DLBufferingDuration; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.DLBufferingSuggestedPacketCount; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDownlinkDataNotificationAcknowledge decodes given bytes as DownlinkDataNotificationAcknowledge.\nfunc ParseDownlinkDataNotificationAcknowledge(b []byte) (*DownlinkDataNotificationAcknowledge, error) {\n\td := &DownlinkDataNotificationAcknowledge{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DownlinkDataNotificationAcknowledge.\nfunc (d *DownlinkDataNotificationAcknowledge) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.DelayValue:\n\t\t\td.DataNotificationDelay = i\n\t\tcase ie.Recovery:\n\t\t\td.Recovery = i\n\t\tcase ie.Throttling:\n\t\t\td.DLLowPriorityTrafficThrottling = i\n\t\tcase ie.IMSI:\n\t\t\td.IMSI = i\n\t\tcase ie.EPCTimer:\n\t\t\td.DLBufferingDuration = i\n\t\tcase ie.IntegerNumber:\n\t\t\td.DLBufferingSuggestedPacketCount = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DownlinkDataNotificationAcknowledge) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.DataNotificationDelay; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.DLLowPriorityTrafficThrottling; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.DLBufferingDuration; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.DLBufferingSuggestedPacketCount; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DownlinkDataNotificationAcknowledge) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DownlinkDataNotificationAcknowledge) MessageTypeName() string {\n\treturn \"Downlink Data Notification Acknowledge\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DownlinkDataNotificationAcknowledge) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/downlink-data-notification-ack_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDownlinkDataNotificationAcknowledge(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDownlinkDataNotificationAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewDelayValue(500*time.Millisecond),\n\t\t\t\tie.NewRecovery(0xff),\n\t\t\t\tie.NewThrottling(20*time.Hour, 80),\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewEPCTimer(20*time.Hour),\n\t\t\t\tie.NewIntegerNumber(2020),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xb1, 0x00, 0x35, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// DataNotificationDelay\n\t\t\t\t0x5c, 0x00, 0x01, 0x00, 0x0a,\n\t\t\t\t// Recovery\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0xff,\n\t\t\t\t// DLLowPriorityTrafficThrottling\n\t\t\t\t0x9a, 0x00, 0x02, 0x00, 0x82, 0x50,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// DLBufferingDuration\n\t\t\t\t0x9c, 0x00, 0x01, 0x00, 0x82,\n\t\t\t\t// DLBufferingSuggestedPacketCount\n\t\t\t\t0xbb, 0x00, 0x02, 0x00, 0x07, 0xe4,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDownlinkDataNotificationAcknowledge(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/downlink-data-notification-failure-indication.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DownlinkDataNotificationFailureIndication is a DownlinkDataNotificationFailureIndication Header and its IEs above.\ntype DownlinkDataNotificationFailureIndication struct {\n\t*Header\n\tCause            *ie.IE\n\tOriginatingNode  *ie.IE\n\tIMSI             *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewDownlinkDataNotificationFailureIndication creates a new DownlinkDataNotificationFailureIndication.\nfunc NewDownlinkDataNotificationFailureIndication(teid, seq uint32, ies ...*ie.IE) *DownlinkDataNotificationFailureIndication {\n\td := &DownlinkDataNotificationFailureIndication{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDownlinkDataNotificationFailureIndication, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.NodeType:\n\t\t\td.OriginatingNode = i\n\t\tcase ie.IMSI:\n\t\t\td.IMSI = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DownlinkDataNotificationFailureIndication into bytes.\nfunc (d *DownlinkDataNotificationFailureIndication) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DownlinkDataNotificationFailureIndication into bytes.\nfunc (d *DownlinkDataNotificationFailureIndication) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.OriginatingNode; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDownlinkDataNotificationFailureIndication decodes given bytes as DownlinkDataNotificationFailureIndication.\nfunc ParseDownlinkDataNotificationFailureIndication(b []byte) (*DownlinkDataNotificationFailureIndication, error) {\n\td := &DownlinkDataNotificationFailureIndication{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DownlinkDataNotificationFailureIndication.\nfunc (d *DownlinkDataNotificationFailureIndication) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.NodeType:\n\t\t\td.OriginatingNode = i\n\t\tcase ie.IMSI:\n\t\t\td.IMSI = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DownlinkDataNotificationFailureIndication) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.OriginatingNode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DownlinkDataNotificationFailureIndication) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DownlinkDataNotificationFailureIndication) MessageTypeName() string {\n\treturn \"Downlink Data Notification Failure Indication\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DownlinkDataNotificationFailureIndication) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/downlink-data-notification-failure-indication_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDownlinkDataNotificationFailureIndication(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDownlinkDataNotificationFailureIndication(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewNodeType(gtpv2.NodeTypeMME),\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x46, 0x00, 0x1f, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// NodeType\n\t\t\t\t0x87, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDownlinkDataNotificationFailureIndication(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/downlink-data-notification.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// DownlinkDataNotification is a DownlinkDataNotification Header and its IEs above.\ntype DownlinkDataNotification struct {\n\t*Header\n\tCause                         *ie.IE\n\tEPSBearerID                   *ie.IE\n\tAllocationRetensionPriority   *ie.IE\n\tIMSI                          *ie.IE\n\tSenderFTEIDC                  *ie.IE\n\tIndicationFlags               *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tPagingAndServiceInformation   *ie.IE\n\tDLDataPacketsSize             *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewDownlinkDataNotification creates a new DownlinkDataNotification.\nfunc NewDownlinkDataNotification(teid, seq uint32, ies ...*ie.IE) *DownlinkDataNotification {\n\td := &DownlinkDataNotification{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeDownlinkDataNotification, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.EPSBearerID:\n\t\t\td.EPSBearerID = i\n\t\tcase ie.AllocationRetensionPriority:\n\t\t\td.AllocationRetensionPriority = i\n\t\tcase ie.IMSI:\n\t\t\td.IMSI = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\td.SenderFTEIDC = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\td.SGWNodeLoadControlInformation = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\td.SGWOverloadControlInformation = i\n\t\tcase ie.PagingAndServiceInformation:\n\t\t\td.PagingAndServiceInformation = i\n\t\tcase ie.IntegerNumber:\n\t\t\td.DLDataPacketsSize = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\td.SetLength()\n\treturn d\n}\n\n// Marshal serializes DownlinkDataNotification into bytes.\nfunc (d *DownlinkDataNotification) Marshal() ([]byte, error) {\n\tb := make([]byte, d.MarshalLen())\n\tif err := d.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes DownlinkDataNotification into bytes.\nfunc (d *DownlinkDataNotification) MarshalTo(b []byte) error {\n\tif d.Header.Payload != nil {\n\t\td.Header.Payload = nil\n\t}\n\td.Header.Payload = make([]byte, d.MarshalLen()-d.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := d.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.EPSBearerID; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.AllocationRetensionPriority; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PagingAndServiceInformation; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.DLDataPacketsSize; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(d.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(d.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\td.Header.SetLength()\n\treturn d.Header.MarshalTo(b)\n}\n\n// ParseDownlinkDataNotification decodes given bytes as DownlinkDataNotification.\nfunc ParseDownlinkDataNotification(b []byte) (*DownlinkDataNotification, error) {\n\td := &DownlinkDataNotification{}\n\tif err := d.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn d, nil\n}\n\n// UnmarshalBinary decodes given bytes as DownlinkDataNotification.\nfunc (d *DownlinkDataNotification) UnmarshalBinary(b []byte) error {\n\tvar err error\n\td.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(d.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(d.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\td.Cause = i\n\t\tcase ie.EPSBearerID:\n\t\t\td.EPSBearerID = i\n\t\tcase ie.AllocationRetensionPriority:\n\t\t\td.AllocationRetensionPriority = i\n\t\tcase ie.IMSI:\n\t\t\td.IMSI = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\td.SenderFTEIDC = i\n\t\tcase ie.Indication:\n\t\t\td.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\td.SGWNodeLoadControlInformation = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\td.SGWOverloadControlInformation = i\n\t\tcase ie.PagingAndServiceInformation:\n\t\t\td.PagingAndServiceInformation = i\n\t\tcase ie.IntegerNumber:\n\t\t\td.DLDataPacketsSize = i\n\t\tcase ie.PrivateExtension:\n\t\t\td.PrivateExtension = i\n\t\tdefault:\n\t\t\td.AdditionalIEs = append(d.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (d *DownlinkDataNotification) MarshalLen() int {\n\tl := d.Header.MarshalLen() - len(d.Header.Payload)\n\n\tif ie := d.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.EPSBearerID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.AllocationRetensionPriority; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PagingAndServiceInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.DLDataPacketsSize; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := d.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range d.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (d *DownlinkDataNotification) SetLength() {\n\td.Header.Length = uint16(d.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (d *DownlinkDataNotification) MessageTypeName() string {\n\treturn \"Downlink Data Notification\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (d *DownlinkDataNotification) TEID() uint32 {\n\treturn d.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/downlink-data-notification_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestDownlinkDataNotification(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewDownlinkDataNotification(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\tie.NewAllocationRetensionPriority(1, 2, 1),\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS4SGSNGTPU, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t\t\tie.NewIndicationFromOctets(0xa1, 0x08),\n\t\t\t\tie.NewPagingAndServiceInformation(5, 0x01, 0xff),\n\t\t\t\tie.NewIntegerNumber(2020),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xb0, 0x00, 0x44, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// ARP\n\t\t\t\t0x9b, 0x00, 0x01, 0x00, 0x49,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// F-TEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// Indication\n\t\t\t\t0x4d, 0x00, 0x02, 0x00, 0xa1, 0x08,\n\t\t\t\t// PagingAndServiceInformation\n\t\t\t\t0xba, 0x00, 0x03, 0x00, 0x05, 0x01, 0x7f,\n\t\t\t\t// DLDataPacketSize\n\t\t\t\t0xbb, 0x00, 0x02, 0x00, 0x07, 0xe4,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseDownlinkDataNotification(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/echo-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// EchoRequest is a EchoRequest Header and its IEs above.\ntype EchoRequest struct {\n\t*Header\n\tRecovery            *ie.IE\n\tSendingNodeFeatures *ie.IE\n\tPrivateExtension    *ie.IE\n\tAdditionalIEs       []*ie.IE\n}\n\n// NewEchoRequest creates a new EchoRequest.\nfunc NewEchoRequest(seq uint32, ies ...*ie.IE) *EchoRequest {\n\te := &EchoRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 0),\n\t\t\tMsgTypeEchoRequest, 0, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.NodeFeatures:\n\t\t\te.SendingNodeFeatures = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EchoRequest.\nfunc (e *EchoRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EchoRequest) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.SendingNodeFeatures; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEchoRequest decodes a given byte sequence as a EchoRequest.\nfunc ParseEchoRequest(b []byte) (*EchoRequest, error) {\n\te := &EchoRequest{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a EchoRequest.\nfunc (e *EchoRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.NodeFeatures:\n\t\t\te.SendingNodeFeatures = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EchoRequest) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.SendingNodeFeatures; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EchoRequest) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EchoRequest) MessageTypeName() string {\n\treturn \"Echo Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (e *EchoRequest) TEID() uint32 {\n\treturn e.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/echo-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes EchoRequest into bytes.\n//\n// Deprecated: use EchoRequest.Marshal instead.\nfunc (e *EchoRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"EchoRequest.Serialize is deprecated. use EchoRequest.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes EchoRequest into bytes given as b.\n//\n// Deprecated: use EchoRequest.MarshalTo instead.\nfunc (e *EchoRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"EchoRequest.SerializeTo is deprecated. use EchoRequest.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeEchoRequest decodes bytes as EchoRequest.\n//\n// Deprecated: use ParseEchoRequest instead.\nfunc DecodeEchoRequest(b []byte) (*EchoRequest, error) {\n\tlog.Println(\"DecodeEchoRequest is deprecated. use ParseEchoRequest instead\")\n\treturn ParseEchoRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as EchoRequest.\n//\n// Deprecated: use EchoRequest.UnmarshalBinary instead.\nfunc (e *EchoRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"EchoRequest.DecodeFromBytes is deprecated. use EchoRequest.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of EchoRequest.\n//\n// Deprecated: use EchoRequest.MarshalLen instead.\nfunc (e *EchoRequest) Len() int {\n\tlog.Println(\"EchoRequest.Len is deprecated. use EchoRequest.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/echo-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestEchoRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewEchoRequest(\n\t\t\t\t0,\n\t\t\t\tie.NewRecovery(0x80),\n\t\t\t\tie.NewNodeFeatures(0x01),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x40, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t// Recovery\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0x80,\n\t\t\t\t// Node Features\n\t\t\t\t0x98, 0x00, 0x01, 0x00, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEchoRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/echo-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// EchoResponse is a EchoResponse Header and its IEs above.\ntype EchoResponse struct {\n\t*Header\n\tRecovery            *ie.IE\n\tSendingNodeFeatures *ie.IE\n\tPrivateExtension    *ie.IE\n\tAdditionalIEs       []*ie.IE\n}\n\n// NewEchoResponse creates a new EchoResponse.\nfunc NewEchoResponse(seq uint32, ies ...*ie.IE) *EchoResponse {\n\te := &EchoResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 0),\n\t\t\tMsgTypeEchoResponse, 0, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.NodeFeatures:\n\t\t\te.SendingNodeFeatures = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\te.SetLength()\n\treturn e\n}\n\n// Marshal returns the byte sequence generated from a EchoResponse.\nfunc (e *EchoResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, e.MarshalLen())\n\tif err := e.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (e *EchoResponse) MarshalTo(b []byte) error {\n\tif e.Header.Payload != nil {\n\t\te.Header.Payload = nil\n\t}\n\te.Header.Payload = make([]byte, e.MarshalLen()-e.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := e.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.SendingNodeFeatures; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(e.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\te.Header.SetLength()\n\treturn e.Header.MarshalTo(b)\n}\n\n// ParseEchoResponse decodes a given byte sequence as a EchoResponse.\nfunc ParseEchoResponse(b []byte) (*EchoResponse, error) {\n\te := &EchoResponse{}\n\tif err := e.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn e, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a EchoResponse.\nfunc (e *EchoResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\te.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(e.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(e.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Recovery:\n\t\t\te.Recovery = i\n\t\tcase ie.NodeFeatures:\n\t\t\te.SendingNodeFeatures = i\n\t\tcase ie.PrivateExtension:\n\t\t\te.PrivateExtension = i\n\t\tdefault:\n\t\t\te.AdditionalIEs = append(e.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (e *EchoResponse) MarshalLen() int {\n\tl := e.Header.MarshalLen() - len(e.Header.Payload)\n\n\tif ie := e.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.SendingNodeFeatures; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := e.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range e.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (e *EchoResponse) SetLength() {\n\te.Header.Length = uint16(e.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (e *EchoResponse) MessageTypeName() string {\n\treturn \"Echo Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (e *EchoResponse) TEID() uint32 {\n\treturn e.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/echo-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes EchoResponse into bytes.\n//\n// Deprecated: use EchoResponse.Marshal instead.\nfunc (e *EchoResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"EchoResponse.Serialize is deprecated. use EchoResponse.Marshal instead\")\n\treturn e.Marshal()\n}\n\n// SerializeTo serializes EchoResponse into bytes given as b.\n//\n// Deprecated: use EchoResponse.MarshalTo instead.\nfunc (e *EchoResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"EchoResponse.SerializeTo is deprecated. use EchoResponse.MarshalTo instead\")\n\treturn e.MarshalTo(b)\n}\n\n// DecodeEchoResponse decodes bytes as EchoResponse.\n//\n// Deprecated: use ParseEchoResponse instead.\nfunc DecodeEchoResponse(b []byte) (*EchoResponse, error) {\n\tlog.Println(\"DecodeEchoResponse is deprecated. use ParseEchoResponse instead\")\n\treturn ParseEchoResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as EchoResponse.\n//\n// Deprecated: use EchoResponse.UnmarshalBinary instead.\nfunc (e *EchoResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"EchoResponse.DecodeFromBytes is deprecated. use EchoResponse.UnmarshalBinary instead\")\n\treturn e.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of EchoResponse.\n//\n// Deprecated: use EchoResponse.MarshalLen instead.\nfunc (e *EchoResponse) Len() int {\n\tlog.Println(\"EchoResponse.Len is deprecated. use EchoResponse.MarshalLen instead\")\n\treturn e.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/echo-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestEchoResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewEchoResponse(\n\t\t\t\t0,\n\t\t\t\tie.NewRecovery(0x80),\n\t\t\t\tie.NewNodeFeatures(0x01),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x40, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t// Recovery\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0x80,\n\t\t\t\t// Node Features\n\t\t\t\t0x98, 0x00, 0x01, 0x00, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseEchoResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/errors.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"errors\"\n\n// Error definitions.\nvar (\n\tErrInvalidLength   = errors.New(\"length value is invalid\")\n\tErrTooShortToParse = errors.New(\"too short to decode as GTP\")\n)\n"
  },
  {
    "path": "gtpv2/message/generic.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// Generic is a Generic formed GTP Header and its IEs above.\ntype Generic struct {\n\t*Header\n\tIEs []*ie.IE\n}\n\n// NewGeneric creates a new Generic.\nfunc NewGeneric(msgType uint8, teid, seq uint32, ie ...*ie.IE) *Generic {\n\tg := &Generic{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0x00, 1),\n\t\t\tmsgType,\n\t\t\tteid, seq,\n\t\t\tnil,\n\t\t),\n\t\tIEs: ie,\n\t}\n\tg.SetLength()\n\n\treturn g\n}\n\n// NewGenericWithoutTEID creates a new Generic.\nfunc NewGenericWithoutTEID(msgType uint8, teid, seq uint32, ie ...*ie.IE) *Generic {\n\tg := &Generic{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0x00, 0),\n\t\t\tmsgType, teid, seq, nil,\n\t\t),\n\t\tIEs: ie,\n\t}\n\n\treturn g\n}\n\n// Marshal returns the byte sequence generated from a Generic.\nfunc (g *Generic) Marshal() ([]byte, error) {\n\tb := make([]byte, g.MarshalLen())\n\tif err := g.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (g *Generic) MarshalTo(b []byte) error {\n\tif g.Header.Payload != nil {\n\t\tg.Header.Payload = nil\n\t}\n\tg.Header.Payload = make([]byte, g.MarshalLen()-g.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range g.IEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(g.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tg.Header.SetLength()\n\treturn g.Header.MarshalTo(b)\n}\n\n// ParseGeneric decodes a given byte sequence as a Generic.\nfunc ParseGeneric(b []byte) (*Generic, error) {\n\tg := &Generic{}\n\tif err := g.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn g, nil\n}\n\n// UnmarshalBinary decodes a given byte sequence as a Generic.\nfunc (g *Generic) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tg.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(g.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tg.IEs, err = ie.ParseMultiIEs(g.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (g *Generic) MarshalLen() int {\n\tl := g.Header.MarshalLen() - len(g.Header.Payload)\n\n\tfor _, ie := range g.IEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (g *Generic) SetLength() {\n\tl := g.Header.MarshalLen() - len(g.Header.Payload) - 4\n\tfor _, ie := range g.IEs {\n\t\tl += ie.MarshalLen()\n\t}\n\tg.Header.Length = uint16(l)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (g *Generic) MessageTypeName() string {\n\treturn fmt.Sprintf(\"Unknown (%d)\", g.Header.Type)\n}\n\n// TEID returns the TEID in uint32.\nfunc (g *Generic) TEID() uint32 {\n\treturn g.Header.teid()\n}\n\n// AddIE add IEs to Generic type of GTPv2 message and update Length field.\nfunc (g *Generic) AddIE(ie ...*ie.IE) {\n\tg.IEs = append(g.IEs, ie...)\n\tg.SetLength()\n}\n"
  },
  {
    "path": "gtpv2/message/generic_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Generic into bytes.\n//\n// Deprecated: use Generic.Marshal instead.\nfunc (g *Generic) Serialize() ([]byte, error) {\n\tlog.Println(\"Generic.Serialize is deprecated. use Generic.Marshal instead\")\n\treturn g.Marshal()\n}\n\n// SerializeTo serializes Generic into bytes given as b.\n//\n// Deprecated: use Generic.MarshalTo instead.\nfunc (g *Generic) SerializeTo(b []byte) error {\n\tlog.Println(\"Generic.SerializeTo is deprecated. use Generic.MarshalTo instead\")\n\treturn g.MarshalTo(b)\n}\n\n// DecodeGeneric decodes bytes as Generic.\n//\n// Deprecated: use ParseGeneric instead.\nfunc DecodeGeneric(b []byte) (*Generic, error) {\n\tlog.Println(\"DecodeGeneric is deprecated. use ParseGeneric instead\")\n\treturn ParseGeneric(b)\n}\n\n// DecodeFromBytes decodes bytes as Generic.\n//\n// Deprecated: use Generic.UnmarshalBinary instead.\nfunc (g *Generic) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"Generic.DecodeFromBytes is deprecated. use Generic.UnmarshalBinary instead\")\n\treturn g.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of Generic.\n//\n// Deprecated: use Generic.MarshalLen instead.\nfunc (g *Generic) Len() int {\n\tlog.Println(\"Generic.Len is deprecated. use Generic.MarshalLen instead\")\n\treturn g.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/generic_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestGeneric(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewGeneric(\n\t\t\t\tmessage.MsgTypeEchoRequest,\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewRecovery(0x80),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x48, 0x01, 0x00, 0x0d, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00,\n\t\t\t\t0x80,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"No-TEID\",\n\t\t\tStructured: message.NewGeneric(\n\t\t\t\tmessage.MsgTypeEchoRequest,\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewRecovery(0x80),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x48, 0x01, 0x00, 0x0d, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00,\n\t\t\t\t0x80,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseGeneric(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/header.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\nconst (\n\tfixedHeaderSize  = 4\n\tseqSpareSize     = 4\n\tteidSize         = 4\n\tnoTEIDHeaderSize = fixedHeaderSize + seqSpareSize\n\tteidHeaderSize   = noTEIDHeaderSize + teidSize\n)\n\n// Header is a GTPv2 common header\ntype Header struct {\n\tFlags          uint8\n\tType           uint8\n\tLength         uint16\n\tTEID           uint32\n\tSequenceNumber uint32\n\tSpare          uint8\n\tPayload        []byte\n}\n\n// NewHeader creates a new Header\nfunc NewHeader(flags, mtype uint8, teid, seqnum uint32, data []byte) *Header {\n\th := &Header{\n\t\tFlags:          flags,\n\t\tType:           mtype,\n\t\tTEID:           teid,\n\t\tSequenceNumber: seqnum,\n\t\tSpare:          0,\n\t\tPayload:        data,\n\t}\n\th.SetLength()\n\n\treturn h\n}\n\n// NewHeaderFlags returns a Header Flag built by its components given as arguments.\nfunc NewHeaderFlags(v, p, t int) uint8 {\n\treturn uint8(\n\t\t((v & 0x7) << 5) | ((p & 0x1) << 4) | ((t & 0x1) << 3),\n\t)\n}\n\n// Marshal returns the byte sequence generated from a Header instance.\nfunc (h *Header) Marshal() ([]byte, error) {\n\tb := make([]byte, h.MarshalLen())\n\tif err := h.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (h *Header) MarshalTo(b []byte) error {\n\tb[0] = h.Flags\n\tb[1] = h.Type\n\tbinary.BigEndian.PutUint16(b[2:4], h.Length)\n\toffset := 4\n\tif h.HasTEID() {\n\t\tbinary.BigEndian.PutUint32(b[offset:offset+4], h.TEID)\n\t\toffset += 4\n\t}\n\tcopy(b[offset:offset+3], utils.Uint32To24(h.SequenceNumber))\n\tb[offset+3] = h.Spare\n\tcopy(b[offset+4:h.MarshalLen()], h.Payload)\n\n\treturn nil\n}\n\n// ParseHeader decodes given byte sequence as a GTPv2 header.\nfunc ParseHeader(b []byte) (*Header, error) {\n\th := &Header{}\n\tif err := h.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn h, nil\n}\n\n// UnmarshalBinary sets the values retrieved from byte sequence in GTPv2 header.\nfunc (h *Header) UnmarshalBinary(b []byte) error {\n\tl := len(b)\n\tif l < 12 {\n\t\treturn ErrTooShortToParse\n\t}\n\th.Flags = b[0]\n\th.Type = b[1]\n\th.Length = binary.BigEndian.Uint16(b[2:4])\n\tif h.Length < seqSpareSize {\n\t\treturn ErrTooShortToParse\n\t}\n\tif h.HasTEID() {\n\t\tif h.Length < seqSpareSize+teidSize {\n\t\t\treturn ErrTooShortToParse\n\t\t}\n\t\th.TEID = binary.BigEndian.Uint32(b[4:8])\n\t\th.SequenceNumber = utils.Uint24To32(b[8:11])\n\t\th.Spare = b[11]\n\n\t\tif int(h.Length)+fixedHeaderSize > l {\n\t\t\th.Payload = b[teidHeaderSize:]\n\t\t\treturn nil\n\t\t}\n\t\tif fixedHeaderSize+h.Length >= teidHeaderSize {\n\t\t\th.Payload = b[teidHeaderSize : fixedHeaderSize+h.Length]\n\t\t} else {\n\t\t\treturn ErrInvalidLength\n\t\t}\n\t\treturn nil\n\t}\n\th.SequenceNumber = utils.Uint24To32(b[4:7])\n\th.Spare = b[7]\n\n\tif int(h.Length)+fixedHeaderSize > l {\n\t\th.Payload = b[noTEIDHeaderSize:]\n\t\treturn nil\n\t}\n\tif fixedHeaderSize+h.Length >= noTEIDHeaderSize {\n\t\th.Payload = b[noTEIDHeaderSize : fixedHeaderSize+h.Length]\n\t} else {\n\t\treturn ErrInvalidLength\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns field length in integer.\nfunc (h *Header) MarshalLen() int {\n\tl := 8 + len(h.Payload)\n\tif h.HasTEID() {\n\t\tl += 4\n\t}\n\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (h *Header) SetLength() {\n\th.Length = uint16(4 + len(h.Payload))\n\tif h.HasTEID() {\n\t\th.Length += 4\n\t}\n}\n\n// String returns the GTPv2 header values in human readable format.\nfunc (h *Header) String() string {\n\treturn fmt.Sprintf(\"{Flags: %#x, Type: %d, Length: %d, TEID: %#x, SequenceNumber: %#x, Spare: %d, Payload: %#v}\",\n\t\th.Flags,\n\t\th.Type,\n\t\th.Length,\n\t\th.TEID,\n\t\th.SequenceNumber,\n\t\th.Spare,\n\t\th.Payload,\n\t)\n}\n\n// IsPiggybacking reports whether the message has the trailing(piggybacked) message.\nfunc (h *Header) IsPiggybacking() bool {\n\treturn (int(h.Flags)>>4)&0x01 == 1\n}\n\n// SetPiggybacking sets the Piggybacking flag.\n//\n// The given value should only be 0 or 1. Otherwise it may cause the unexpected result.\nfunc (h *Header) SetPiggybacking(val uint8) {\n\th.Flags = (h.Flags & 0xef) | (val & 0x01 << 4)\n}\n\n// HasTEID determines whether a GTPv2 has TEID inside by checking the flag.\nfunc (h *Header) HasTEID() bool {\n\treturn (int(h.Flags)>>3)&0x01 == 1\n}\n\nfunc (h *Header) teid() uint32 {\n\tif !h.HasTEID() {\n\t\treturn 0\n\t}\n\treturn h.TEID\n}\n\n// SetTEID sets the TEIDFlag to 1 and puts the TEID given into TEID field.\nfunc (h *Header) SetTEID(teid uint32) {\n\th.Flags |= (1 << 3)\n\th.TEID = teid\n}\n\n// Sequence returns SequenceNumber in uint32.\nfunc (h *Header) Sequence() uint32 {\n\treturn h.SequenceNumber\n}\n\n// SetSequenceNumber sets the SequenceNumber in Header.\nfunc (h *Header) SetSequenceNumber(seq uint32) {\n\th.SequenceNumber = seq\n}\n\n// HasMessagePriority reports whether the message has MessagePriority field\nfunc (h *Header) HasMessagePriority() bool {\n\treturn (int(h.Flags)>>2)&0x01 == 1\n}\n\n// SetMessagePriority sets the MessagePriorityFlag to 1 and puts the MessagePriority\n// given into MessagePriority field.\nfunc (h *Header) SetMessagePriority(mp uint8) {\n\th.Flags |= (1 << 2)\n\th.Spare = (mp & 0xf0)\n}\n\n// MessagePriority returns the value of MessagePriority.\n//\n// Note that this returns the value set in the field even if the MessagePriorityFlag\n// is not set to 1.\nfunc (h *Header) MessagePriority() uint8 {\n\treturn h.Spare & 0xf0\n}\n\n// Version returns the GTP version.\nfunc (h *Header) Version() int {\n\treturn 2\n}\n\n// MessageType returns the type of messagg.\nfunc (h *Header) MessageType() uint8 {\n\treturn h.Type\n}\n"
  },
  {
    "path": "gtpv2/message/header_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Header into bytes.\n//\n// Deprecated: use Header.Marshal instead.\nfunc (h *Header) Serialize() ([]byte, error) {\n\tlog.Println(\"Header.Serialize is deprecated. use Header.Marshal instead\")\n\treturn h.Marshal()\n}\n\n// SerializeTo serializes Header into bytes given as b.\n//\n// Deprecated: use Header.MarshalTo instead.\nfunc (h *Header) SerializeTo(b []byte) error {\n\tlog.Println(\"Header.SerializeTo is deprecated. use Header.MarshalTo instead\")\n\treturn h.MarshalTo(b)\n}\n\n// DecodeHeader decodes bytes as Header.\n//\n// Deprecated: use ParseHeader instead.\nfunc DecodeHeader(b []byte) (*Header, error) {\n\tlog.Println(\"DecodeHeader is deprecated. use ParseHeader instead\")\n\treturn ParseHeader(b)\n}\n\n// DecodeFromBytes decodes bytes as Header.\n//\n// Deprecated: use Header.UnmarshalBinary instead.\nfunc (h *Header) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"Header.DecodeFromBytes is deprecated. use Header.UnmarshalBinary instead\")\n\treturn h.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of Header.\n//\n// Deprecated: use Header.MarshalLen instead.\nfunc (h *Header) Len() int {\n\tlog.Println(\"Header.Len is deprecated. use Header.MarshalLen instead\")\n\treturn h.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/header_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestHeader(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewHeader(\n\t\t\t\tmessage.NewHeaderFlags(2, 0, 1),\n\t\t\t\t32,         // Message type\n\t\t\t\t0xffffffff, // TEID\n\t\t\t\t0xdadada,   // Sequence Number\n\t\t\t\t[]byte{ // Payload: IMSI IE\n\t\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t},\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x48, 0x20, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff,\n\t\t\t\t0xda, 0xda, 0xda, 0x00,\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseHeader(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/message.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n/*\nPackage message provides encoding/decoding feature of GTPv2 protocol.\n*/\npackage message\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// Message Type definitions.\nconst (\n\t_ uint8 = iota\n\tMsgTypeEchoRequest\n\tMsgTypeEchoResponse\n\tMsgTypeVersionNotSupportedIndication\n\tMsgTypeDirectTransferRequest\n\tMsgTypeDirectTransferResponse\n\tMsgTypeNotificationRequest\n\tMsgTypeNotificationResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 8-16: Reserved for S101 interface\n\tMsgTypeRIMInformationTransfer\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 18-24: Reserved for S121 interface\n\tMsgTypeSRVCCPsToCsRequest\n\tMsgTypeSRVCCPsToCsResponse\n\tMsgTypeSRVCCPsToCsCompleteNotification\n\tMsgTypeSRVCCPsToCsCompleteAcknowledge\n\tMsgTypeSRVCCPsToCsCancelNotification\n\tMsgTypeSRVCCPsToCsCancelAcknowledge\n\tMsgTypeSRVCCCsToPsRequest\n\tMsgTypeCreateSessionRequest\n\tMsgTypeCreateSessionResponse\n\tMsgTypeModifyBearerRequest\n\tMsgTypeModifyBearerResponse\n\tMsgTypeDeleteSessionRequest\n\tMsgTypeDeleteSessionResponse\n\tMsgTypeChangeNotificationRequest\n\tMsgTypeChangeNotificationResponse\n\tMsgTypeRemoteUEReportNotification\n\tMsgTypeRemoteUEReportAcknowledge\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 42-63: Reserved for S4/S11, S5/S8 interfaces\n\tMsgTypeModifyBearerCommand\n\tMsgTypeModifyBearerFailureIndication\n\tMsgTypeDeleteBearerCommand\n\tMsgTypeDeleteBearerFailureIndication\n\tMsgTypeBearerResourceCommand\n\tMsgTypeBearerResourceFailureIndication\n\tMsgTypeDownlinkDataNotificationFailureIndication\n\tMsgTypeTraceSessionActivation\n\tMsgTypeTraceSessionDeactivation\n\tMsgTypeStopPagingIndication\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 74-94: Reserved for GTPv2 non-specific interfaces\n\tMsgTypeCreateBearerRequest\n\tMsgTypeCreateBearerResponse\n\tMsgTypeUpdateBearerRequest\n\tMsgTypeUpdateBearerResponse\n\tMsgTypeDeleteBearerRequest\n\tMsgTypeDeleteBearerResponse\n\tMsgTypeDeletePDNConnectionSetRequest\n\tMsgTypeDeletePDNConnectionSetResponse\n\tMsgTypePGWDownlinkTriggeringNotification\n\tMsgTypePGWDownlinkTriggeringAcknowledge\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 105-127: Reserved for S5, S4/S11 interfaces\n\tMsgTypeIdentificationRequest\n\tMsgTypeIdentificationResponse\n\tMsgTypeContextRequest\n\tMsgTypeContextResponse\n\tMsgTypeContextAcknowledge\n\tMsgTypeForwardRelocationRequest\n\tMsgTypeForwardRelocationResponse\n\tMsgTypeForwardRelocationCompleteNotification\n\tMsgTypeForwardRelocationCompleteAcknowledge\n\tMsgTypeForwardAccessContextNotification\n\tMsgTypeForwardAccessContextAcknowledge\n\tMsgTypeRelocationCancelRequest\n\tMsgTypeRelocationCancelResponse\n\tMsgTypeConfigurationTransferTunnel\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 142-148: Reserved for S3/S10/S16 interfaces\n\tMsgTypeDetachNotification\n\tMsgTypeDetachAcknowledge\n\tMsgTypeCSPagingIndication\n\tMsgTypeRANInformationRelay\n\tMsgTypeAlertMMENotification\n\tMsgTypeAlertMMEAcknowledge\n\tMsgTypeUEActivityNotification\n\tMsgTypeUEActivityAcknowledge\n\tMsgTypeISRStatusIndication\n\tMsgTypeUERegistrationQueryRequest\n\tMsgTypeUERegistrationQueryResponse\n\tMsgTypeCreateForwardingTunnelRequest\n\tMsgTypeCreateForwardingTunnelResponse\n\tMsgTypeSuspendNotification\n\tMsgTypeSuspendAcknowledge\n\tMsgTypeResumeNotification\n\tMsgTypeResumeAcknowledge\n\tMsgTypeCreateIndirectDataForwardingTunnelRequest\n\tMsgTypeCreateIndirectDataForwardingTunnelResponse\n\tMsgTypeDeleteIndirectDataForwardingTunnelRequest\n\tMsgTypeDeleteIndirectDataForwardingTunnelResponse\n\tMsgTypeReleaseAccessBearersRequest\n\tMsgTypeReleaseAccessBearersResponse\n\t_\n\t_\n\t_\n\t_ // 172-175: Reserved for S4/S11 interfaces\n\tMsgTypeDownlinkDataNotification\n\tMsgTypeDownlinkDataNotificationAcknowledge\n\t_\n\tMsgTypePGWRestartNotification\n\tMsgTypePGWRestartNotificationAcknowledge\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 181-199: Reserved for S4 interface\n\tMsgTypeUpdatePDNConnectionSetRequest\n\tMsgTypeUpdatePDNConnectionSetResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 202-210: Reserved for S5/S8 interfaces\n\tMsgTypeModifyAccessBearersRequest\n\tMsgTypeModifyAccessBearersResponse\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 213-230: Reserved for S11 interface\n\tMsgTypeMBMSSessionStartRequest\n\tMsgTypeMBMSSessionStartResponse\n\tMsgTypeMBMSSessionUpdateRequest\n\tMsgTypeMBMSSessionUpdateResponse\n\tMsgTypeMBMSSessionStopRequest\n\tMsgTypeMBMSSessionStopResponse\n\t_\n\t_\n\t_ // 237-239: Reserved for Sm/Sn interface\n\tMsgTypeSRVCCCsToPsResponse\n\tMsgTypeSRVCCCsToPsCompleteNotification\n\tMsgTypeSRVCCCsToPsCompleteAcknowledge\n\tMsgTypeSRVCCCsToPsCancelNotification\n\tMsgTypeSRVCCCsToPsCancelAcknowledge\n\t_\n\t_\n\t_ // 245-247: Reserved for Sv interface\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_\n\t_ // 248-255: Reserved for others\n)\n\n// Message is an interface that defines GTPv2 message.\ntype Message interface {\n\tMarshalTo([]byte) error\n\tUnmarshalBinary(b []byte) error\n\tMarshalLen() int\n\tVersion() int\n\tMessageType() uint8\n\tMessageTypeName() string\n\tTEID() uint32\n\tSetTEID(uint32)\n\tSequence() uint32\n\tSetSequenceNumber(uint32)\n\n\t// deprecated\n\tSerializeTo([]byte) error\n\tDecodeFromBytes(b []byte) error\n}\n\n// Marshal returns the byte sequence generated from a Message instance.\n// Better to use MarshalXxx instead if you know the name of message to be serialized.\nfunc Marshal(m Message) ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// Parse decodes the given bytes as Message.\nfunc Parse(b []byte) (Message, error) {\n\tvar m Message\n\n\tif len(b) < 2 {\n\t\treturn nil, io.ErrUnexpectedEOF\n\t}\n\n\tswitch b[1] {\n\tcase MsgTypeEchoRequest:\n\t\tm = &EchoRequest{}\n\tcase MsgTypeEchoResponse:\n\t\tm = &EchoResponse{}\n\tcase MsgTypeVersionNotSupportedIndication:\n\t\tm = &VersionNotSupportedIndication{}\n\tcase MsgTypeCreateSessionRequest:\n\t\tm = &CreateSessionRequest{}\n\tcase MsgTypeCreateSessionResponse:\n\t\tm = &CreateSessionResponse{}\n\tcase MsgTypeDeleteSessionRequest:\n\t\tm = &DeleteSessionRequest{}\n\tcase MsgTypeDeleteSessionResponse:\n\t\tm = &DeleteSessionResponse{}\n\tcase MsgTypeModifyBearerCommand:\n\t\tm = &ModifyBearerCommand{}\n\tcase MsgTypeModifyBearerFailureIndication:\n\t\tm = &ModifyBearerFailureIndication{}\n\tcase MsgTypeDeleteBearerCommand:\n\t\tm = &DeleteBearerCommand{}\n\tcase MsgTypeDeleteBearerFailureIndication:\n\t\tm = &DeleteBearerFailureIndication{}\n\tcase MsgTypeDeleteBearerRequest:\n\t\tm = &DeleteBearerRequest{}\n\tcase MsgTypeCreateBearerRequest:\n\t\tm = &CreateBearerRequest{}\n\tcase MsgTypeCreateBearerResponse:\n\t\tm = &CreateBearerResponse{}\n\tcase MsgTypeDeleteBearerResponse:\n\t\tm = &DeleteBearerResponse{}\n\tcase MsgTypeModifyBearerRequest:\n\t\tm = &ModifyBearerRequest{}\n\tcase MsgTypeModifyBearerResponse:\n\t\tm = &ModifyBearerResponse{}\n\tcase MsgTypeUpdateBearerRequest:\n\t\tm = &UpdateBearerRequest{}\n\tcase MsgTypeUpdateBearerResponse:\n\t\tm = &UpdateBearerResponse{}\n\tcase MsgTypeContextRequest:\n\t\tm = &ContextRequest{}\n\tcase MsgTypeContextResponse:\n\t\tm = &ContextResponse{}\n\tcase MsgTypeContextAcknowledge:\n\t\tm = &ContextAcknowledge{}\n\tcase MsgTypeReleaseAccessBearersRequest:\n\t\tm = &ReleaseAccessBearersRequest{}\n\tcase MsgTypeReleaseAccessBearersResponse:\n\t\tm = &ReleaseAccessBearersResponse{}\n\tcase MsgTypeStopPagingIndication:\n\t\tm = &StopPagingIndication{}\n\tcase MsgTypeModifyAccessBearersRequest:\n\t\tm = &ModifyAccessBearersRequest{}\n\tcase MsgTypeModifyAccessBearersResponse:\n\t\tm = &ModifyAccessBearersResponse{}\n\tcase MsgTypeDeletePDNConnectionSetRequest:\n\t\tm = &DeletePDNConnectionSetRequest{}\n\tcase MsgTypeDeletePDNConnectionSetResponse:\n\t\tm = &DeletePDNConnectionSetResponse{}\n\tcase MsgTypeUpdatePDNConnectionSetRequest:\n\t\tm = &UpdatePDNConnectionSetRequest{}\n\tcase MsgTypeUpdatePDNConnectionSetResponse:\n\t\tm = &UpdatePDNConnectionSetResponse{}\n\tcase MsgTypePGWRestartNotification:\n\t\tm = &PGWRestartNotification{}\n\tcase MsgTypePGWRestartNotificationAcknowledge:\n\t\tm = &PGWRestartNotificationAcknowledge{}\n\tcase MsgTypeDetachNotification:\n\t\tm = &DetachNotification{}\n\tcase MsgTypeDetachAcknowledge:\n\t\tm = &DetachAcknowledge{}\n\tcase MsgTypeResumeAcknowledge:\n\t\tm = &ResumeAcknowledge{}\n\tcase MsgTypeResumeNotification:\n\t\tm = &ResumeNotification{}\n\tcase MsgTypeSuspendAcknowledge:\n\t\tm = &SuspendAcknowledge{}\n\tcase MsgTypeSuspendNotification:\n\t\tm = &SuspendNotification{}\n\tcase MsgTypeChangeNotificationRequest:\n\t\tm = &ChangeNotificationRequest{}\n\tcase MsgTypeChangeNotificationResponse:\n\t\tm = &ChangeNotificationResponse{}\n\tcase MsgTypeDownlinkDataNotification:\n\t\tm = &DownlinkDataNotification{}\n\tcase MsgTypeDownlinkDataNotificationAcknowledge:\n\t\tm = &DownlinkDataNotificationAcknowledge{}\n\tcase MsgTypeDownlinkDataNotificationFailureIndication:\n\t\tm = &DownlinkDataNotificationFailureIndication{}\n\tdefault:\n\t\tm = &Generic{}\n\t}\n\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode GTPv2 Message: %w\", err)\n\t}\n\treturn m, nil\n}\n\n// Prettify returns a Message in prettified representation in string.\n//\n// Note that this relies much on reflect package, and thus the frequent use of\n// this function may have a serious impact on the performance of your software.\nfunc Prettify(m Message) string {\n\tname := m.MessageTypeName()\n\theader := strings.TrimSuffix(fmt.Sprint(m), \"}\")\n\n\tv := reflect.Indirect(reflect.ValueOf(m))\n\tn := v.NumField() - 1\n\tfields := make([]*field, n)\n\tfor i := 1; i < n+1; i++ { // Skip *Header\n\t\tfields[i-1] = &field{name: v.Type().Field(i).Name, maybeIE: v.Field(i).Interface()}\n\t}\n\n\treturn fmt.Sprintf(\"{%s: %s, IEs: [%v]}\", name, header, strings.Join(prettifyFields(fields), \", \"))\n}\n\ntype field struct {\n\tname    string\n\tmaybeIE interface{}\n}\n\nfunc prettifyFields(fields []*field) []string {\n\tret := []string{}\n\tfor _, field := range fields {\n\t\tif field.maybeIE == nil {\n\t\t\tret = append(ret, prettifyIE(field.name, nil))\n\t\t\tcontinue\n\t\t}\n\n\t\t// TODO: do this recursively?\n\t\tv, ok := field.maybeIE.(*ie.IE)\n\t\tif !ok {\n\t\t\t// only for AdditionalIEs field\n\t\t\tif ies, ok := field.maybeIE.([]*ie.IE); ok {\n\t\t\t\tvals := make([]string, len(ies))\n\t\t\t\tfor i, val := range ies {\n\t\t\t\t\tvals[i] = fmt.Sprint(val)\n\t\t\t\t}\n\t\t\t\tret = append(ret, fmt.Sprintf(\"{%s: [%v]}\", field.name, strings.Join(vals, \", \")))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tret = append(ret, prettifyIE(field.name, v))\n\t}\n\n\treturn ret\n}\n\nfunc prettifyIE(name string, i *ie.IE) string {\n\tif i == nil {\n\t\treturn fmt.Sprintf(\"{%s: %v}\", name, i)\n\t}\n\n\tif i.IsGrouped() {\n\t\tvals := make([]string, len(i.ChildIEs))\n\t\tfor i, val := range i.ChildIEs {\n\t\t\tvals[i] = fmt.Sprint(val)\n\t\t}\n\t\treturn fmt.Sprintf(\"{%s: [%v]}\", name, strings.Join(vals, \", \"))\n\t}\n\n\treturn fmt.Sprintf(\"{%s: %v}\", name, i)\n}\n"
  },
  {
    "path": "gtpv2/message/message_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes Message into bytes.\n//\n// Deprecated: use Marshal instead.\nfunc Serialize(m Message) ([]byte, error) {\n\tlog.Println(\"Serialize is deprecated. use Marshal instead\")\n\treturn Marshal(m)\n}\n\n// Decode decodes bytes as Message.\n//\n// Deprecated: use Parse instead.\nfunc Decode(b []byte) (Message, error) {\n\tlog.Println(\"Decode is deprecated. use Parse instead\")\n\treturn Parse(b)\n}\n"
  },
  {
    "path": "gtpv2/message/message_fuzz_test.go",
    "content": "//go:build go1.18\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\nfunc FuzzParse(f *testing.F) {\n\ttestcases := [][]byte{\n\t\t{0x10, 0x20, 0x30},\n\t\t{0x48, 0x20, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff, 0xda, 0xda, 0xda},\n\t}\n\tfor _, tc := range testcases {\n\t\tf.Add(tc)\n\t}\n\n\tf.Fuzz(func(t *testing.T, data []byte) {\n\t\tif v, err := message.Parse(data); err == nil && v == nil {\n\t\t\tt.Errorf(\"nil without error\")\n\t\t}\n\t})\n}\n\nfunc FuzzHeaderParse(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, b []byte) {\n\t\tif _, err := message.ParseHeader(b); err != nil {\n\t\t\tt.Skip()\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/message_test.go",
    "content": "package message_test\n\nimport (\n\t\"net\"\n)\n\nvar (\n\tmac1, _ = net.ParseMAC(\"12:34:56:78:90:01\")\n\tmac2, _ = net.ParseMAC(\"12:34:56:78:90:02\")\n)\n"
  },
  {
    "path": "gtpv2/message/modify-access-bearers-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ModifyAccessBearersRequest is a ModifyAccessBearersRequest Header and its IEs above.\ntype ModifyAccessBearersRequest struct {\n\t*Header\n\tIndicationFlags                        *ie.IE\n\tSenderFTEIDC                           *ie.IE\n\tDelayDownlinkPacketNotificationRequest *ie.IE\n\tBearerContextsToBeModified             []*ie.IE\n\tBearerContextsToBeRemoved              []*ie.IE\n\tRecovery                               *ie.IE\n\tSecondaryRATUsageDataReport            []*ie.IE\n\tPrivateExtension                       *ie.IE\n\tAdditionalIEs                          []*ie.IE\n}\n\n// NewModifyAccessBearersRequest creates a new ModifyAccessBearersRequest.\nfunc NewModifyAccessBearersRequest(teid, seq uint32, ies ...*ie.IE) *ModifyAccessBearersRequest {\n\tm := &ModifyAccessBearersRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeModifyAccessBearersRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.NodeType:\n\t\t\tm.SenderFTEIDC = i\n\t\tcase ie.DelayValue:\n\t\t\tm.DelayDownlinkPacketNotificationRequest = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsToBeModified = append(m.BearerContextsToBeModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsToBeRemoved = append(m.BearerContextsToBeRemoved, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tm.SecondaryRATUsageDataReport = append(m.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes ModifyAccessBearersRequest into bytes.\nfunc (m *ModifyAccessBearersRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ModifyAccessBearersRequest into bytes.\nfunc (m *ModifyAccessBearersRequest) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.DelayDownlinkPacketNotificationRequest; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeModified {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeRemoved {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.SecondaryRATUsageDataReport {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseModifyAccessBearersRequest decodes given bytes as ModifyAccessBearersRequest.\nfunc ParseModifyAccessBearersRequest(b []byte) (*ModifyAccessBearersRequest, error) {\n\tm := &ModifyAccessBearersRequest{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as ModifyAccessBearersRequest.\nfunc (m *ModifyAccessBearersRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.NodeType:\n\t\t\tm.SenderFTEIDC = i\n\t\tcase ie.DelayValue:\n\t\t\tm.DelayDownlinkPacketNotificationRequest = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsToBeModified = append(m.BearerContextsToBeModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsToBeRemoved = append(m.BearerContextsToBeRemoved, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tm.SecondaryRATUsageDataReport = append(m.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *ModifyAccessBearersRequest) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.DelayDownlinkPacketNotificationRequest; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeModified {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeRemoved {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.SecondaryRATUsageDataReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *ModifyAccessBearersRequest) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *ModifyAccessBearersRequest) MessageTypeName() string {\n\treturn \"Modify Access Bearers Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *ModifyAccessBearersRequest) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-access-bearers-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ModifyAccessBearersRequest into bytes.\n//\n// Deprecated: use ModifyAccessBearersRequest.Marshal instead.\nfunc (m *ModifyAccessBearersRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"ModifyAccessBearersRequest.Serialize is deprecated. use ModifyAccessBearersRequest.Marshal instead\")\n\treturn m.Marshal()\n}\n\n// SerializeTo serializes ModifyAccessBearersRequest into bytes given as b.\n//\n// Deprecated: use ModifyAccessBearersRequest.MarshalTo instead.\nfunc (m *ModifyAccessBearersRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"ModifyAccessBearersRequest.SerializeTo is deprecated. use ModifyAccessBearersRequest.MarshalTo instead\")\n\treturn m.MarshalTo(b)\n}\n\n// DecodeModifyAccessBearersRequest decodes bytes as ModifyAccessBearersRequest.\n//\n// Deprecated: use ParseModifyAccessBearersRequest instead.\nfunc DecodeModifyAccessBearersRequest(b []byte) (*ModifyAccessBearersRequest, error) {\n\tlog.Println(\"DecodeModifyAccessBearersRequest is deprecated. use ParseModifyAccessBearersRequest instead\")\n\treturn ParseModifyAccessBearersRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as ModifyAccessBearersRequest.\n//\n// Deprecated: use ModifyAccessBearersRequest.UnmarshalBinary instead.\nfunc (m *ModifyAccessBearersRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ModifyAccessBearersRequest.DecodeFromBytes is deprecated. use ModifyAccessBearersRequest.UnmarshalBinary instead\")\n\treturn m.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ModifyAccessBearersRequest.\n//\n// Deprecated: use ModifyAccessBearersRequest.MarshalLen instead.\nfunc (m *ModifyAccessBearersRequest) Len() int {\n\tlog.Println(\"ModifyAccessBearersRequest.Len is deprecated. use ModifyAccessBearersRequest.MarshalLen instead\")\n\treturn m.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-access-bearers-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestModifyAccessBearersRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/NoIE\",\n\t\t\tStructured: message.NewModifyAccessBearersRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xd3, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"Normal/WithIndication\",\n\t\t\tStructured: message.NewModifyAccessBearersRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIndicationFromOctets(0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xd3, 0x00, 0x3f, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Indication\n\t\t\t\t0x4d, 0x00, 0x07, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseModifyAccessBearersRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/modify-access-bearers-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ModifyAccessBearersResponse is a ModifyAccessBearersResponse Header and its IEs above.\ntype ModifyAccessBearersResponse struct {\n\t*Header\n\tCause                          *ie.IE\n\tBearerContextsModified         []*ie.IE\n\tBearerContextsMarkedForRemoval []*ie.IE\n\tRecovery                       *ie.IE\n\tIndicationFlags                *ie.IE\n\tSGWNodeLoadControlInformation  *ie.IE\n\tSGWOverloadControlInformation  *ie.IE\n\tPrivateExtension               *ie.IE\n\tAdditionalIEs                  []*ie.IE\n}\n\n// NewModifyAccessBearersResponse creates a new ModifyAccessBearersResponse.\nfunc NewModifyAccessBearersResponse(teid, seq uint32, ies ...*ie.IE) *ModifyAccessBearersResponse {\n\tm := &ModifyAccessBearersResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeModifyAccessBearersResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsModified = append(m.BearerContextsModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsMarkedForRemoval = append(m.BearerContextsMarkedForRemoval, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tm.SGWNodeLoadControlInformation = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tm.SGWOverloadControlInformation = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes ModifyAccessBearersResponse into bytes.\nfunc (m *ModifyAccessBearersResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ModifyAccessBearersResponse into bytes.\nfunc (m *ModifyAccessBearersResponse) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsModified {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsMarkedForRemoval {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseModifyAccessBearersResponse decodes given bytes as ModifyAccessBearersResponse.\nfunc ParseModifyAccessBearersResponse(b []byte) (*ModifyAccessBearersResponse, error) {\n\tm := &ModifyAccessBearersResponse{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as ModifyAccessBearersResponse.\nfunc (m *ModifyAccessBearersResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsModified = append(m.BearerContextsModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsMarkedForRemoval = append(m.BearerContextsMarkedForRemoval, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tm.SGWNodeLoadControlInformation = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tm.SGWOverloadControlInformation = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *ModifyAccessBearersResponse) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsModified {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsMarkedForRemoval {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *ModifyAccessBearersResponse) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *ModifyAccessBearersResponse) MessageTypeName() string {\n\treturn \"Modify Access Bearers Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *ModifyAccessBearersResponse) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-access-bearers-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ModifyAccessBearersResponse into bytes.\n//\n// Deprecated: use ModifyAccessBearersResponse.Marshal instead.\nfunc (m *ModifyAccessBearersResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"ModifyAccessBearersResponse.Serialize is deprecated. use ModifyAccessBearersResponse.Marshal instead\")\n\treturn m.Marshal()\n}\n\n// SerializeTo serializes ModifyAccessBearersResponse into bytes given as b.\n//\n// Deprecated: use ModifyAccessBearersResponse.MarshalTo instead.\nfunc (m *ModifyAccessBearersResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"ModifyAccessBearersResponse.SerializeTo is deprecated. use ModifyAccessBearersResponse.MarshalTo instead\")\n\treturn m.MarshalTo(b)\n}\n\n// DecodeModifyAccessBearersResponse decodes bytes as ModifyAccessBearersResponse.\n//\n// Deprecated: use ParseModifyAccessBearersResponse instead.\nfunc DecodeModifyAccessBearersResponse(b []byte) (*ModifyAccessBearersResponse, error) {\n\tlog.Println(\"DecodeModifyAccessBearersResponse is deprecated. use ParseModifyAccessBearersResponse instead\")\n\treturn ParseModifyAccessBearersResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as ModifyAccessBearersResponse.\n//\n// Deprecated: use ModifyAccessBearersResponse.UnmarshalBinary instead.\nfunc (m *ModifyAccessBearersResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ModifyAccessBearersResponse.DecodeFromBytes is deprecated. use ModifyAccessBearersResponse.UnmarshalBinary instead\")\n\treturn m.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ModifyAccessBearersResponse.\n//\n// Deprecated: use ModifyAccessBearersResponse.MarshalLen instead.\nfunc (m *ModifyAccessBearersResponse) Len() int {\n\tlog.Println(\"ModifyAccessBearersResponse.Len is deprecated. use ModifyAccessBearersResponse.MarshalLen instead\")\n\treturn m.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-access-bearers-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestModifyAccessBearersResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/CauseOnly\",\n\t\t\tStructured: message.NewModifyAccessBearersResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xd4, 0x00, 0x3a, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseModifyAccessBearersResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-command.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ModifyBearerCommand is a ModifyBearerCommand Header and its IEs above.\ntype ModifyBearerCommand struct {\n\t*Header\n\tAPNAMBR                            *ie.IE\n\tBearerContext                      *ie.IE\n\tMMESGSNOverloadControlInformation  *ie.IE\n\tSGWOverloadControlInformation      *ie.IE\n\tTWANePDGOverloadControlInformation *ie.IE\n\tSenderFTEIDC                       *ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewModifyBearerCommand creates a new ModifyBearerCommand.\nfunc NewModifyBearerCommand(teid, seq uint32, ies ...*ie.IE) *ModifyBearerCommand {\n\tm := &ModifyBearerCommand{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeModifyBearerCommand, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tm.APNAMBR = i\n\t\tcase ie.BearerContext:\n\t\t\tm.BearerContext = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tm.TWANePDGOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tm.SenderFTEIDC = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes ModifyBearerCommand into bytes.\nfunc (m *ModifyBearerCommand) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ModifyBearerCommand into bytes.\nfunc (m *ModifyBearerCommand) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.APNAMBR; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.BearerContext; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.TWANePDGOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseModifyBearerCommand decodes given bytes as ModifyBearerCommand.\nfunc ParseModifyBearerCommand(b []byte) (*ModifyBearerCommand, error) {\n\tm := &ModifyBearerCommand{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as ModifyBearerCommand.\nfunc (m *ModifyBearerCommand) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tm.APNAMBR = i\n\t\tcase ie.BearerContext:\n\t\t\tm.BearerContext = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tm.TWANePDGOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tm.SenderFTEIDC = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *ModifyBearerCommand) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\tif ie := m.APNAMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.BearerContext; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.TWANePDGOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *ModifyBearerCommand) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *ModifyBearerCommand) MessageTypeName() string {\n\treturn \"Modify Bearer Command\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *ModifyBearerCommand) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-command_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestModifyBearerCommand(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewModifyBearerCommand(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewAggregateMaximumBitRate(0x11111111, 0x22222222),\n\t\t\t\tie.NewBearerContext(ie.NewDelayValue(500*time.Millisecond), ie.NewDelayValue(100*time.Millisecond)),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x40, 0x00, 0x22, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// APN-AMBR\n\t\t\t\t0x48, 0x00, 0x08, 0x00, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22,\n\t\t\t\t// BearerContext\n\t\t\t\t0x5d, 0x00, 0x0a, 0x00, 0x5c, 0x00, 0x01, 0x00, 0x0a, 0x5c, 0x00, 0x01, 0x00, 0x02,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseModifyBearerCommand(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-failure-indication.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ModifyBearerFailureIndication is a ModifyBearerFailureIndication Header and its IEs above.\ntype ModifyBearerFailureIndication struct {\n\t*Header\n\tCause                         *ie.IE\n\tRecovery                      *ie.IE\n\tIndicationFlags               *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewModifyBearerFailureIndication creates a new ModifyBearerFailureIndication.\nfunc NewModifyBearerFailureIndication(teid, seq uint32, ies ...*ie.IE) *ModifyBearerFailureIndication {\n\tm := &ModifyBearerFailureIndication{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeModifyBearerFailureIndication, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes ModifyBearerFailureIndication into bytes.\nfunc (m *ModifyBearerFailureIndication) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ModifyBearerFailureIndication into bytes.\nfunc (m *ModifyBearerFailureIndication) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseModifyBearerFailureIndication decodes given bytes as ModifyBearerFailureIndication.\nfunc ParseModifyBearerFailureIndication(b []byte) (*ModifyBearerFailureIndication, error) {\n\tm := &ModifyBearerFailureIndication{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as ModifyBearerFailureIndication.\nfunc (m *ModifyBearerFailureIndication) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *ModifyBearerFailureIndication) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *ModifyBearerFailureIndication) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *ModifyBearerFailureIndication) MessageTypeName() string {\n\treturn \"Modify Bearer Failure Indication\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *ModifyBearerFailureIndication) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-failure-indication_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestModifyBearerFailureIndication(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewModifyBearerFailureIndication(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x41, 0x00, 0x0e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseModifyBearerFailureIndication(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ModifyBearerRequest is a ModifyBearerRequest Header and its IEs above.\ntype ModifyBearerRequest struct {\n\t*Header\n\tMEI                                    *ie.IE\n\tULI                                    *ie.IE\n\tServingNetwork                         *ie.IE\n\tRATType                                *ie.IE\n\tIndicationFlags                        *ie.IE\n\tSenderFTEIDC                           *ie.IE\n\tAMBR                                   *ie.IE\n\tDelayDownlinkPacketNotificationRequest *ie.IE\n\tBearerContextsToBeModified             []*ie.IE\n\tBearerContextsToBeRemoved              []*ie.IE\n\tRecovery                               *ie.IE\n\tUETimeZone                             *ie.IE\n\tMMEFQCSID                              *ie.IE\n\tSGWFQCSID                              *ie.IE\n\tUCI                                    *ie.IE\n\tUELocalIPAddress                       *ie.IE\n\tUEUDPPort                              *ie.IE\n\tMMESGSNLDN                             *ie.IE\n\tSGWLDN                                 *ie.IE\n\tHeNBLocalIPAddress                     *ie.IE\n\tHeNBUDPPort                            *ie.IE\n\tMMESGSNIdentifier                      *ie.IE\n\tCNOperatorSelectionEntity              *ie.IE\n\tPresenceReportingAreaInformation       []*ie.IE\n\tMMESGSNOverloadControlInformation      *ie.IE\n\tSGWOverloadControlInformation          *ie.IE\n\tEPDGOverloadControlInformation         *ie.IE\n\tServingPLMNRateControl                 *ie.IE\n\tMOExceptionDataCounter                 *ie.IE\n\tIMSI                                   *ie.IE\n\tULIForSGW                              *ie.IE\n\tWLANLocationInformation                *ie.IE\n\tWLANLocationTimeStamp                  *ie.IE\n\tSecondaryRATUsageDataReport            []*ie.IE\n\tPrivateExtension                       *ie.IE\n\tAdditionalIEs                          []*ie.IE\n}\n\n// NewModifyBearerRequest creates a new ModifyBearerRequest.\nfunc NewModifyBearerRequest(teid, seq uint32, ies ...*ie.IE) *ModifyBearerRequest {\n\tm := &ModifyBearerRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeModifyBearerRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tm.MEI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.ULI = i\n\t\t\tcase 1:\n\t\t\t\tm.ULIForSGW = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ServingNetwork:\n\t\t\tm.ServingNetwork = i\n\t\tcase ie.RATType:\n\t\t\tm.RATType = i\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tm.SenderFTEIDC = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tm.AMBR = i\n\t\tcase ie.DelayValue:\n\t\t\tm.DelayDownlinkPacketNotificationRequest = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsToBeModified = append(m.BearerContextsToBeModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsToBeRemoved = append(m.BearerContextsToBeRemoved, i)\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.UETimeZone:\n\t\t\tm.UETimeZone = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.UserCSGInformation:\n\t\t\tm.UCI = i\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.UELocalIPAddress = i\n\t\t\tcase 1:\n\t\t\t\tm.HeNBLocalIPAddress = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tm.HeNBUDPPort = i\n\t\t\tcase 2:\n\t\t\t\tm.MMESGSNIdentifier = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMESGSNLDN = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWLDN = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tm.CNOperatorSelectionEntity = i\n\t\tcase ie.PresenceReportingAreaInformation:\n\t\t\tm.PresenceReportingAreaInformation = append(m.PresenceReportingAreaInformation, i)\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tm.EPDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ServingPLMNRateControl:\n\t\t\tm.ServingPLMNRateControl = i\n\t\tcase ie.Counter:\n\t\t\tm.MOExceptionDataCounter = i\n\t\tcase ie.IMSI:\n\t\t\tm.IMSI = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tm.WLANLocationInformation = i\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tm.WLANLocationTimeStamp = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tm.SecondaryRATUsageDataReport = append(m.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes ModifyBearerRequest into bytes.\nfunc (m *ModifyBearerRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ModifyBearerRequest into bytes.\nfunc (m *ModifyBearerRequest) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.MEI; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ServingNetwork; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.RATType; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.AMBR; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.DelayDownlinkPacketNotificationRequest; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeModified {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeRemoved {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.UCI; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.UELocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.UEUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNLDN; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWLDN; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.HeNBLocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.HeNBUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.CNOperatorSelectionEntity; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.PresenceReportingAreaInformation {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.EPDGOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ServingPLMNRateControl; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MOExceptionDataCounter; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ULIForSGW; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.WLANLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.WLANLocationTimeStamp; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.SecondaryRATUsageDataReport {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseModifyBearerRequest decodes given bytes as ModifyBearerRequest.\nfunc ParseModifyBearerRequest(b []byte) (*ModifyBearerRequest, error) {\n\tc := &ModifyBearerRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ModifyBearerRequest.\nfunc (m *ModifyBearerRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.MobileEquipmentIdentity:\n\t\t\tm.MEI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.ULI = i\n\t\t\tcase 1:\n\t\t\t\tm.ULIForSGW = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ServingNetwork:\n\t\t\tm.ServingNetwork = i\n\t\tcase ie.RATType:\n\t\t\tm.RATType = i\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tm.SenderFTEIDC = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tm.AMBR = i\n\t\tcase ie.DelayValue:\n\t\t\tm.DelayDownlinkPacketNotificationRequest = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsToBeModified = append(m.BearerContextsToBeModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsToBeRemoved = append(m.BearerContextsToBeRemoved, i)\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.UETimeZone:\n\t\t\tm.UETimeZone = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.UserCSGInformation:\n\t\t\tm.UCI = i\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.UELocalIPAddress = i\n\t\t\tcase 1:\n\t\t\t\tm.HeNBLocalIPAddress = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tm.HeNBUDPPort = i\n\t\t\tcase 2:\n\t\t\t\tm.MMESGSNIdentifier = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMESGSNLDN = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWLDN = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.CNOperatorSelectionEntity:\n\t\t\tm.CNOperatorSelectionEntity = i\n\t\tcase ie.PresenceReportingAreaInformation:\n\t\t\tm.PresenceReportingAreaInformation = append(m.PresenceReportingAreaInformation, i)\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tm.EPDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ServingPLMNRateControl:\n\t\t\tm.ServingPLMNRateControl = i\n\t\tcase ie.Counter:\n\t\t\tm.MOExceptionDataCounter = i\n\t\tcase ie.IMSI:\n\t\t\tm.IMSI = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tm.WLANLocationInformation = i\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tm.WLANLocationTimeStamp = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tm.SecondaryRATUsageDataReport = append(m.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *ModifyBearerRequest) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.MEI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ServingNetwork; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.RATType; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.AMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.DelayDownlinkPacketNotificationRequest; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeModified {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsToBeRemoved {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.UCI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.UELocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.UEUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.HeNBLocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.HeNBUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.CNOperatorSelectionEntity; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.PresenceReportingAreaInformation {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MMESGSNOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.EPDGOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ServingPLMNRateControl; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MOExceptionDataCounter; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ULIForSGW; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.WLANLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.WLANLocationTimeStamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.SecondaryRATUsageDataReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *ModifyBearerRequest) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *ModifyBearerRequest) MessageTypeName() string {\n\treturn \"Modify Bearer Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *ModifyBearerRequest) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ModifyBearerRequest into bytes.\n//\n// Deprecated: use ModifyBearerRequest.Marshal instead.\nfunc (m *ModifyBearerRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"ModifyBearerRequest.Serialize is deprecated. use ModifyBearerRequest.Marshal instead\")\n\treturn m.Marshal()\n}\n\n// SerializeTo serializes ModifyBearerRequest into bytes given as b.\n//\n// Deprecated: use ModifyBearerRequest.MarshalTo instead.\nfunc (m *ModifyBearerRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"ModifyBearerRequest.SerializeTo is deprecated. use ModifyBearerRequest.MarshalTo instead\")\n\treturn m.MarshalTo(b)\n}\n\n// DecodeModifyBearerRequest decodes bytes as ModifyBearerRequest.\n//\n// Deprecated: use ParseModifyBearerRequest instead.\nfunc DecodeModifyBearerRequest(b []byte) (*ModifyBearerRequest, error) {\n\tlog.Println(\"DecodeModifyBearerRequest is deprecated. use ParseModifyBearerRequest instead\")\n\treturn ParseModifyBearerRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as ModifyBearerRequest.\n//\n// Deprecated: use ModifyBearerRequest.UnmarshalBinary instead.\nfunc (m *ModifyBearerRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ModifyBearerRequest.DecodeFromBytes is deprecated. use ModifyBearerRequest.UnmarshalBinary instead\")\n\treturn m.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ModifyBearerRequest.\n//\n// Deprecated: use ModifyBearerRequest.MarshalLen instead.\nfunc (m *ModifyBearerRequest) Len() int {\n\tlog.Println(\"ModifyBearerRequest.Len is deprecated. use ModifyBearerRequest.MarshalLen instead\")\n\treturn m.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestModifyBearerRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/FromMMEtoSGW\",\n\t\t\tStructured: message.NewModifyBearerRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x22, 0x00, 0x34, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseModifyBearerRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ModifyBearerResponse is a ModifyBearerResponse Header and its IEs above.\ntype ModifyBearerResponse struct {\n\t*Header\n\tCause                          *ie.IE\n\tMSISDN                         *ie.IE\n\tLinkedEBI                      *ie.IE\n\tAPNRestriction                 *ie.IE\n\tPCO                            *ie.IE\n\tBearerContextsModified         []*ie.IE\n\tBearerContextsMarkedForRemoval []*ie.IE\n\tChangeReportingAction          *ie.IE\n\tCSGInformationReportingAction  *ie.IE\n\tHeNBInformationReporting       *ie.IE\n\tChargingGatewayName            *ie.IE\n\tChargingGatewayAddress         *ie.IE\n\tPGWFQCSID                      *ie.IE\n\tSGWFQCSID                      *ie.IE\n\tRecovery                       *ie.IE\n\tSGWLDN                         *ie.IE\n\tPGWLDN                         *ie.IE\n\tIndicationFlags                *ie.IE\n\tPresenceReportingAreaAction    []*ie.IE\n\tPGWNodeLoadControlInformation  *ie.IE\n\tPGWAPNLoadControlInformation   *ie.IE\n\tSGWNodeLoadControlInformation  *ie.IE\n\tPGWOverloadControlInformation  *ie.IE\n\tSGWOverloadControlInformation  *ie.IE\n\tPDNConnectionChargingID        *ie.IE\n\tPrivateExtension               *ie.IE\n\tAdditionalIEs                  []*ie.IE\n}\n\n// NewModifyBearerResponse creates a new ModifyBearerResponse.\nfunc NewModifyBearerResponse(teid, seq uint32, ies ...*ie.IE) *ModifyBearerResponse {\n\tm := &ModifyBearerResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeModifyBearerResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.MSISDN:\n\t\t\tm.MSISDN = i\n\t\tcase ie.EPSBearerID:\n\t\t\tm.LinkedEBI = i\n\t\tcase ie.APNRestriction:\n\t\t\tm.APNRestriction = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tm.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsModified = append(m.BearerContextsModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsMarkedForRemoval = append(m.BearerContextsMarkedForRemoval, i)\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ChangeReportingAction:\n\t\t\tm.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tm.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tm.HeNBInformationReporting = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tm.ChargingGatewayName = i\n\t\tcase ie.IPAddress:\n\t\t\tm.ChargingGatewayAddress = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.SGWLDN = i\n\t\t\tcase 1:\n\t\t\t\tm.PGWLDN = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tm.PresenceReportingAreaAction = append(m.PresenceReportingAreaAction, i)\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.PGWAPNLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.SGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.PGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ChargingID:\n\t\t\tm.PDNConnectionChargingID = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes ModifyBearerResponse into bytes.\nfunc (m *ModifyBearerResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ModifyBearerResponse into bytes.\nfunc (m *ModifyBearerResponse) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.MSISDN; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.APNRestriction; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsModified {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsMarkedForRemoval {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.HeNBInformationReporting; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ChargingGatewayName; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.ChargingGatewayAddress; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWLDN; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWLDN; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.PresenceReportingAreaAction {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWAPNLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PDNConnectionChargingID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseModifyBearerResponse decodes given bytes as ModifyBearerResponse.\nfunc ParseModifyBearerResponse(b []byte) (*ModifyBearerResponse, error) {\n\tm := &ModifyBearerResponse{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as ModifyBearerResponse.\nfunc (m *ModifyBearerResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.MSISDN:\n\t\t\tm.MSISDN = i\n\t\tcase ie.EPSBearerID:\n\t\t\tm.LinkedEBI = i\n\t\tcase ie.APNRestriction:\n\t\t\tm.APNRestriction = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tm.PCO = i\n\t\tcase ie.BearerContext:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.BearerContextsModified = append(m.BearerContextsModified, i)\n\t\t\tcase 1:\n\t\t\t\tm.BearerContextsMarkedForRemoval = append(m.BearerContextsMarkedForRemoval, i)\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ChangeReportingAction:\n\t\t\tm.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tm.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tm.HeNBInformationReporting = i\n\t\tcase ie.FullyQualifiedDomainName:\n\t\t\tm.ChargingGatewayName = i\n\t\tcase ie.IPAddress:\n\t\t\tm.ChargingGatewayAddress = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.LocalDistinguishedName:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.SGWLDN = i\n\t\t\tcase 1:\n\t\t\t\tm.PGWLDN = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Indication:\n\t\t\tm.IndicationFlags = i\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tm.PresenceReportingAreaAction = append(m.PresenceReportingAreaAction, i)\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.PGWAPNLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.SGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tm.PGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tm.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.ChargingID:\n\t\t\tm.PDNConnectionChargingID = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *ModifyBearerResponse) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.MSISDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.APNRestriction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsModified {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.BearerContextsMarkedForRemoval {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.HeNBInformationReporting; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ChargingGatewayName; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.ChargingGatewayAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWLDN; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range m.PresenceReportingAreaAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWAPNLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PDNConnectionChargingID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *ModifyBearerResponse) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *ModifyBearerResponse) MessageTypeName() string {\n\treturn \"Modify Bearer Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *ModifyBearerResponse) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ModifyBearerResponse into bytes.\n//\n// Deprecated: use ModifyBearerResponse.Marshal instead.\nfunc (m *ModifyBearerResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"ModifyBearerResponse.Serialize is deprecated. use ModifyBearerResponse.Marshal instead\")\n\treturn m.Marshal()\n}\n\n// SerializeTo serializes ModifyBearerResponse into bytes given as b.\n//\n// Deprecated: use ModifyBearerResponse.MarshalTo instead.\nfunc (m *ModifyBearerResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"ModifyBearerResponse.SerializeTo is deprecated. use ModifyBearerResponse.MarshalTo instead\")\n\treturn m.MarshalTo(b)\n}\n\n// DecodeModifyBearerResponse decodes bytes as ModifyBearerResponse.\n//\n// Deprecated: use ParseModifyBearerResponse instead.\nfunc DecodeModifyBearerResponse(b []byte) (*ModifyBearerResponse, error) {\n\tlog.Println(\"DecodeModifyBearerResponse is deprecated. use ParseModifyBearerResponse instead\")\n\treturn ParseModifyBearerResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as ModifyBearerResponse.\n//\n// Deprecated: use ModifyBearerResponse.UnmarshalBinary instead.\nfunc (m *ModifyBearerResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ModifyBearerResponse.DecodeFromBytes is deprecated. use ModifyBearerResponse.UnmarshalBinary instead\")\n\treturn m.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ModifyBearerResponse.\n//\n// Deprecated: use ModifyBearerResponse.MarshalLen instead.\nfunc (m *ModifyBearerResponse) Len() int {\n\tlog.Println(\"ModifyBearerResponse.Len is deprecated. use ModifyBearerResponse.MarshalLen instead\")\n\treturn m.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/modify-bearer-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestModifyBearerResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/FromSGWtoMME\",\n\t\t\tStructured: message.NewModifyBearerResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x23, 0x00, 0x46, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x18, 0x00,\n\t\t\t\t//   Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x18, 0x00,\n\t\t\t\t//   Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseModifyBearerResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/pgw-restart-notification-acknowledge.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// PGWRestartNotificationAcknowledge is a PGWRestartNotificationAcknowledge Header and its IEs above.\ntype PGWRestartNotificationAcknowledge struct {\n\t*Header\n\tCause            *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewPGWRestartNotificationAcknowledge creates a new PGWRestartNotificationAcknowledge.\nfunc NewPGWRestartNotificationAcknowledge(teid, seq uint32, ies ...*ie.IE) *PGWRestartNotificationAcknowledge {\n\tm := &PGWRestartNotificationAcknowledge{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypePGWRestartNotificationAcknowledge, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes PGWRestartNotificationAcknowledge into bytes.\nfunc (m *PGWRestartNotificationAcknowledge) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes PGWRestartNotificationAcknowledge into bytes.\nfunc (m *PGWRestartNotificationAcknowledge) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParsePGWRestartNotificationAcknowledge decodes given bytes as PGWRestartNotificationAcknowledge.\nfunc ParsePGWRestartNotificationAcknowledge(b []byte) (*PGWRestartNotificationAcknowledge, error) {\n\tm := &PGWRestartNotificationAcknowledge{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as PGWRestartNotificationAcknowledge.\nfunc (m *PGWRestartNotificationAcknowledge) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *PGWRestartNotificationAcknowledge) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *PGWRestartNotificationAcknowledge) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *PGWRestartNotificationAcknowledge) MessageTypeName() string {\n\treturn \"PGW Restart Notification Acknowledge\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *PGWRestartNotificationAcknowledge) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/pgw-restart-notification-acknowledge_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestPGWRestartNotificationAcknowledge(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewPGWRestartNotificationAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CausePGWNotResponding, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xb4, 0x00, 0x0e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x0c, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParsePGWRestartNotificationAcknowledge(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/pgw-restart-notification.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// PGWRestartNotification is a PGWRestartNotification Header and its IEs above.\ntype PGWRestartNotification struct {\n\t*Header\n\tPGWS5S8IPAddressForControlPlaneOrPMIP *ie.IE\n\tSGWS11S4IPAddressForControlPlane      *ie.IE\n\tCause                                 *ie.IE\n\tPrivateExtension                      *ie.IE\n\tAdditionalIEs                         []*ie.IE\n}\n\n// NewPGWRestartNotification creates a new PGWRestartNotification.\nfunc NewPGWRestartNotification(teid, seq uint32, ies ...*ie.IE) *PGWRestartNotification {\n\tm := &PGWRestartNotification{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypePGWRestartNotification, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWS5S8IPAddressForControlPlaneOrPMIP = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWS11S4IPAddressForControlPlane = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes PGWRestartNotification into bytes.\nfunc (m *PGWRestartNotification) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes PGWRestartNotification into bytes.\nfunc (m *PGWRestartNotification) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.PGWS5S8IPAddressForControlPlaneOrPMIP; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWS11S4IPAddressForControlPlane; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParsePGWRestartNotification decodes given bytes as PGWRestartNotification.\nfunc ParsePGWRestartNotification(b []byte) (*PGWRestartNotification, error) {\n\tm := &PGWRestartNotification{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as PGWRestartNotification.\nfunc (m *PGWRestartNotification) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.PGWS5S8IPAddressForControlPlaneOrPMIP = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWS11S4IPAddressForControlPlane = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *PGWRestartNotification) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.PGWS5S8IPAddressForControlPlaneOrPMIP; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWS11S4IPAddressForControlPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *PGWRestartNotification) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *PGWRestartNotification) MessageTypeName() string {\n\treturn \"PGW Restart Notification\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *PGWRestartNotification) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/pgw-restart-notification_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestPGWRestartNotification(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewPGWRestartNotification(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIPAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewIPAddress(\"1.1.1.1\").WithInstance(1),\n\t\t\t\tie.NewCause(gtpv2.CausePGWNotResponding, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xb3, 0x00, 0x1e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// P-GW IP\n\t\t\t\t0x4a, 0x00, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// S-GW IP\n\t\t\t\t0x4a, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x0c, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParsePGWRestartNotification(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/release-access-bearers-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ReleaseAccessBearersRequest is a ReleaseAccessBearersRequest Header and its IEs above.\ntype ReleaseAccessBearersRequest struct {\n\t*Header\n\tListOfRABs                  []*ie.IE\n\tOriginatingNode             *ie.IE\n\tIndicationFlags             *ie.IE\n\tSecondaryRATUsageDataReport []*ie.IE\n\tPrivateExtension            *ie.IE\n\tAdditionalIEs               []*ie.IE\n}\n\n// NewReleaseAccessBearersRequest creates a new ReleaseAccessBearersRequest.\nfunc NewReleaseAccessBearersRequest(teid, seq uint32, ies ...*ie.IE) *ReleaseAccessBearersRequest {\n\tr := &ReleaseAccessBearersRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeReleaseAccessBearersRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.EPSBearerID:\n\t\t\tr.ListOfRABs = append(r.ListOfRABs, i)\n\t\tcase ie.NodeType:\n\t\t\tr.OriginatingNode = i\n\t\tcase ie.Indication:\n\t\t\tr.IndicationFlags = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tr.SecondaryRATUsageDataReport = append(r.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tr.PrivateExtension = i\n\t\tdefault:\n\t\t\tr.AdditionalIEs = append(r.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tr.SetLength()\n\treturn r\n}\n\n// Marshal serializes ReleaseAccessBearersRequest into bytes.\nfunc (r *ReleaseAccessBearersRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, r.MarshalLen())\n\tif err := r.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ReleaseAccessBearersRequest into bytes.\nfunc (r *ReleaseAccessBearersRequest) MarshalTo(b []byte) error {\n\tif r.Header.Payload != nil {\n\t\tr.Header.Payload = nil\n\t}\n\tr.Header.Payload = make([]byte, r.MarshalLen()-r.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range r.ListOfRABs {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.OriginatingNode; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range r.SecondaryRATUsageDataReport {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range r.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(r.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tr.Header.SetLength()\n\treturn r.Header.MarshalTo(b)\n}\n\n// ParseReleaseAccessBearersRequest decodes given bytes as ReleaseAccessBearersRequest.\nfunc ParseReleaseAccessBearersRequest(b []byte) (*ReleaseAccessBearersRequest, error) {\n\tr := &ReleaseAccessBearersRequest{}\n\tif err := r.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn r, nil\n}\n\n// UnmarshalBinary decodes given bytes as ReleaseAccessBearersRequest.\nfunc (r *ReleaseAccessBearersRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tr.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(r.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(r.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.EPSBearerID:\n\t\t\tr.ListOfRABs = append(r.ListOfRABs, i)\n\t\tcase ie.NodeType:\n\t\t\tr.OriginatingNode = i\n\t\tcase ie.Indication:\n\t\t\tr.IndicationFlags = i\n\t\tcase ie.SecondaryRATUsageDataReport:\n\t\t\tr.SecondaryRATUsageDataReport = append(r.SecondaryRATUsageDataReport, i)\n\t\tcase ie.PrivateExtension:\n\t\t\tr.PrivateExtension = i\n\t\tdefault:\n\t\t\tr.AdditionalIEs = append(r.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (r *ReleaseAccessBearersRequest) MarshalLen() int {\n\tl := r.Header.MarshalLen() - len(r.Header.Payload)\n\tfor _, ie := range r.ListOfRABs {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.OriginatingNode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range r.SecondaryRATUsageDataReport {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range r.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (r *ReleaseAccessBearersRequest) SetLength() {\n\tr.Header.Length = uint16(r.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (r *ReleaseAccessBearersRequest) MessageTypeName() string {\n\treturn \"Release Access Bearers Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (r *ReleaseAccessBearersRequest) TEID() uint32 {\n\treturn r.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/release-access-bearers-req_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ReleaseAccessBearersRequest into bytes.\n//\n// Deprecated: use ReleaseAccessBearersRequest.Marshal instead.\nfunc (r *ReleaseAccessBearersRequest) Serialize() ([]byte, error) {\n\tlog.Println(\"ReleaseAccessBearersRequest.Serialize is deprecated. use ReleaseAccessBearersRequest.Marshal instead\")\n\treturn r.Marshal()\n}\n\n// SerializeTo serializes ReleaseAccessBearersRequest into bytes given as b.\n//\n// Deprecated: use ReleaseAccessBearersRequest.MarshalTo instead.\nfunc (r *ReleaseAccessBearersRequest) SerializeTo(b []byte) error {\n\tlog.Println(\"ReleaseAccessBearersRequest.SerializeTo is deprecated. use ReleaseAccessBearersRequest.MarshalTo instead\")\n\treturn r.MarshalTo(b)\n}\n\n// DecodeReleaseAccessBearersRequest decodes bytes as ReleaseAccessBearersRequest.\n//\n// Deprecated: use ParseReleaseAccessBearersRequest instead.\nfunc DecodeReleaseAccessBearersRequest(b []byte) (*ReleaseAccessBearersRequest, error) {\n\tlog.Println(\"DecodeReleaseAccessBearersRequest is deprecated. use ParseReleaseAccessBearersRequest instead\")\n\treturn ParseReleaseAccessBearersRequest(b)\n}\n\n// DecodeFromBytes decodes bytes as ReleaseAccessBearersRequest.\n//\n// Deprecated: use ReleaseAccessBearersRequest.UnmarshalBinary instead.\nfunc (r *ReleaseAccessBearersRequest) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ReleaseAccessBearersRequest.DecodeFromBytes is deprecated. use ReleaseAccessBearersRequest.UnmarshalBinary instead\")\n\treturn r.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ReleaseAccessBearersRequest.\n//\n// Deprecated: use ReleaseAccessBearersRequest.MarshalLen instead.\nfunc (r *ReleaseAccessBearersRequest) Len() int {\n\tlog.Println(\"ReleaseAccessBearersRequest.Len is deprecated. use ReleaseAccessBearersRequest.MarshalLen instead\")\n\treturn r.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/release-access-bearers-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestReleaseAccessBearersRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/NoIE\",\n\t\t\tStructured: message.NewReleaseAccessBearersRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xaa, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t},\n\t\t}, {\n\t\t\tDescription: \"Normal/WithIndication\",\n\t\t\tStructured: message.NewReleaseAccessBearersRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIndicationFromOctets(0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xaa, 0x00, 0x3f, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Indication\n\t\t\t\t0x4d, 0x00, 0x07, 0x00, 0xa1, 0x08, 0x15, 0x10, 0x88, 0x81, 0x40,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseReleaseAccessBearersRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/release-access-bearers-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// ReleaseAccessBearersResponse is a ReleaseAccessBearersResponse Header and its IEs above.\ntype ReleaseAccessBearersResponse struct {\n\t*Header\n\tCause                         *ie.IE\n\tRecovery                      *ie.IE\n\tIndicationFlags               *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewReleaseAccessBearersResponse creates a new ReleaseAccessBearersResponse.\nfunc NewReleaseAccessBearersResponse(teid, seq uint32, ies ...*ie.IE) *ReleaseAccessBearersResponse {\n\tr := &ReleaseAccessBearersResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeReleaseAccessBearersResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tr.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tr.Recovery = i\n\t\tcase ie.Indication:\n\t\t\tr.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tr.SGWNodeLoadControlInformation = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tr.SGWOverloadControlInformation = i\n\t\tcase ie.PrivateExtension:\n\t\t\tr.PrivateExtension = i\n\t\tdefault:\n\t\t\tr.AdditionalIEs = append(r.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tr.SetLength()\n\treturn r\n}\n\n// Marshal serializes ReleaseAccessBearersResponse into bytes.\nfunc (r *ReleaseAccessBearersResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, r.MarshalLen())\n\tif err := r.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ReleaseAccessBearersResponse into bytes.\nfunc (r *ReleaseAccessBearersResponse) MarshalTo(b []byte) error {\n\tif r.Header.Payload != nil {\n\t\tr.Header.Payload = nil\n\t}\n\tr.Header.Payload = make([]byte, r.MarshalLen()-r.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := r.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := r.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(r.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range r.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(r.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tr.Header.SetLength()\n\treturn r.Header.MarshalTo(b)\n}\n\n// ParseReleaseAccessBearersResponse decodes given bytes as ReleaseAccessBearersResponse.\nfunc ParseReleaseAccessBearersResponse(b []byte) (*ReleaseAccessBearersResponse, error) {\n\tr := &ReleaseAccessBearersResponse{}\n\tif err := r.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn r, nil\n}\n\n// UnmarshalBinary decodes given bytes as ReleaseAccessBearersResponse.\nfunc (r *ReleaseAccessBearersResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tr.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(r.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(r.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tr.Cause = i\n\t\tcase ie.Recovery:\n\t\t\tr.Recovery = i\n\t\tcase ie.Indication:\n\t\t\tr.IndicationFlags = i\n\t\tcase ie.LoadControlInformation:\n\t\t\tr.SGWNodeLoadControlInformation = i\n\t\tcase ie.OverloadControlInformation:\n\t\t\tr.SGWOverloadControlInformation = i\n\t\tcase ie.PrivateExtension:\n\t\t\tr.PrivateExtension = i\n\t\tdefault:\n\t\t\tr.AdditionalIEs = append(r.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (r *ReleaseAccessBearersResponse) MarshalLen() int {\n\tl := r.Header.MarshalLen() - len(r.Header.Payload)\n\n\tif ie := r.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := r.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range r.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (r *ReleaseAccessBearersResponse) SetLength() {\n\tr.Header.Length = uint16(r.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (r *ReleaseAccessBearersResponse) MessageTypeName() string {\n\treturn \"Release Access Bearers Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (r *ReleaseAccessBearersResponse) TEID() uint32 {\n\treturn r.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/release-access-bearers-res_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes ReleaseAccessBearersResponse into bytes.\n//\n// Deprecated: use ReleaseAccessBearersResponse.Marshal instead.\nfunc (r *ReleaseAccessBearersResponse) Serialize() ([]byte, error) {\n\tlog.Println(\"ReleaseAccessBearersResponse.Serialize is deprecated. use ReleaseAccessBearersResponse.Marshal instead\")\n\treturn r.Marshal()\n}\n\n// SerializeTo serializes ReleaseAccessBearersResponse into bytes given as b.\n//\n// Deprecated: use ReleaseAccessBearersResponse.MarshalTo instead.\nfunc (r *ReleaseAccessBearersResponse) SerializeTo(b []byte) error {\n\tlog.Println(\"ReleaseAccessBearersResponse.SerializeTo is deprecated. use ReleaseAccessBearersResponse.MarshalTo instead\")\n\treturn r.MarshalTo(b)\n}\n\n// DecodeReleaseAccessBearersResponse decodes bytes as ReleaseAccessBearersResponse.\n//\n// Deprecated: use ParseReleaseAccessBearersResponse instead.\nfunc DecodeReleaseAccessBearersResponse(b []byte) (*ReleaseAccessBearersResponse, error) {\n\tlog.Println(\"DecodeReleaseAccessBearersResponse is deprecated. use ParseReleaseAccessBearersResponse instead\")\n\treturn ParseReleaseAccessBearersResponse(b)\n}\n\n// DecodeFromBytes decodes bytes as ReleaseAccessBearersResponse.\n//\n// Deprecated: use ReleaseAccessBearersResponse.UnmarshalBinary instead.\nfunc (r *ReleaseAccessBearersResponse) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"ReleaseAccessBearersResponse.DecodeFromBytes is deprecated. use ReleaseAccessBearersResponse.UnmarshalBinary instead\")\n\treturn r.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of ReleaseAccessBearersResponse.\n//\n// Deprecated: use ReleaseAccessBearersResponse.MarshalLen instead.\nfunc (r *ReleaseAccessBearersResponse) Len() int {\n\tlog.Println(\"ReleaseAccessBearersResponse.Len is deprecated. use ReleaseAccessBearersResponse.MarshalLen instead\")\n\treturn r.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/release-access-bearers-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestReleaseAccessBearersResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/CauseOnly\",\n\t\t\tStructured: message.NewReleaseAccessBearersResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xab, 0x00, 0x0e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseReleaseAccessBearersResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/resume-acknowledge.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ResumeAcknowledge is a ResumeAcknowledge Header and its Cause and Private Extension IEs.\ntype ResumeAcknowledge struct {\n\t*Header\n\tCause            *ie.IE\n\tPrivateExtension *ie.IE\n}\n\n// NewResumeAcknowledge creates a new ResumeAcknowledge.\nfunc NewResumeAcknowledge(teid, seq uint32, ies ...*ie.IE) *ResumeAcknowledge {\n\tc := &ResumeAcknowledge{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeResumeAcknowledge, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ResumeAcknowledge into bytes.\nfunc (c *ResumeAcknowledge) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ResumeAcknowledge into bytes.\nfunc (c *ResumeAcknowledge) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseResumeAcknowledge decodes given bytes as ResumeAcknowledge.\nfunc ParseResumeAcknowledge(b []byte) (*ResumeAcknowledge, error) {\n\tc := &ResumeAcknowledge{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ResumeAcknowledge.\nfunc (c *ResumeAcknowledge) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ResumeAcknowledge) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ResumeAcknowledge) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ResumeAcknowledge) MessageTypeName() string {\n\treturn \"Resume Acknowledge\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ResumeAcknowledge) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/resume-acknowledge_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestResumeAcknowledge(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Just Cause\",\n\t\t\tStructured: message.NewResumeAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 165, 0x00, 14, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tDescription: \"With Private Extension\",\n\t\t\tStructured: message.NewResumeAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewPrivateExtension(234, []byte{2, 3, 4, 5, 6}),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 165, 0x00, 25, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// Private Extension\n\t\t\t\t0xff, 0x00, 0x07, 0x00, 0x00, 234, 2, 3, 4, 5, 6,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseResumeAcknowledge(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/resume-notification.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// ResumeNotification is a ResumeNotification Header and its IEs.\ntype ResumeNotification struct {\n\t*Header\n\tIMSI                       *ie.IE\n\tLinkedEPSBearerID          *ie.IE\n\tOriginatingNode            *ie.IE\n\tSenderFTEIDForControlPlane *ie.IE\n\tPrivateExtension           *ie.IE\n}\n\n// NewResumeNotification creates a new ResumeNotification.\nfunc NewResumeNotification(teid, seq uint32, ies ...*ie.IE) *ResumeNotification {\n\tc := &ResumeNotification{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeResumeNotification, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEPSBearerID = i\n\t\tcase ie.NodeType:\n\t\t\tc.OriginatingNode = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.SenderFTEIDForControlPlane = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes ResumeNotification into bytes.\nfunc (c *ResumeNotification) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes ResumeNotification into bytes.\nfunc (c *ResumeNotification) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEPSBearerID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.OriginatingNode; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDForControlPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseResumeNotification decodes given bytes as ResumeNotification.\nfunc ParseResumeNotification(b []byte) (*ResumeNotification, error) {\n\tc := &ResumeNotification{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as ResumeNotification.\nfunc (c *ResumeNotification) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEPSBearerID = i\n\t\tcase ie.NodeType:\n\t\t\tc.OriginatingNode = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.SenderFTEIDForControlPlane = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *ResumeNotification) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEPSBearerID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.OriginatingNode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDForControlPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *ResumeNotification) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *ResumeNotification) MessageTypeName() string {\n\treturn \"Resume Notification\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *ResumeNotification) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/resume-notification_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestResumeNotification(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewResumeNotification(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewEPSBearerID(5),\n\t\t\t\tie.NewNodeType(gtpv2.NodeTypeMME),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS10MMEGTPC, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t\t\tie.NewPrivateExtension(256, []byte{4, 5, 6, 7}),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 164, 0x00, 53, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// EPSBearerID\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// NodeType\n\t\t\t\t0x87, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// FullyQualifiedTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8c, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// PrivateExtension\n\t\t\t\t0xff, 0x00, 0x06, 0x00, 1, 0, 4, 5, 6, 7,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseResumeNotification(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/stop-paging-indication.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\n// StopPagingIndication is a StopPagingIndication Header and its IEs above.\ntype StopPagingIndication struct {\n\t*Header\n\tIMSI             *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewStopPagingIndication creates a new StopPagingIndication.\nfunc NewStopPagingIndication(teid, seq uint32, ies ...*ie.IE) *StopPagingIndication {\n\ts := &StopPagingIndication{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeStopPagingIndication, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\ts.IMSI = i\n\t\tcase ie.PrivateExtension:\n\t\t\ts.PrivateExtension = i\n\t\tdefault:\n\t\t\ts.AdditionalIEs = append(s.AdditionalIEs, i)\n\t\t}\n\t}\n\n\ts.SetLength()\n\treturn s\n}\n\n// Marshal serializes StopPagingIndication into bytes.\nfunc (s *StopPagingIndication) Marshal() ([]byte, error) {\n\tb := make([]byte, s.MarshalLen())\n\tif err := s.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes StopPagingIndication into bytes.\nfunc (s *StopPagingIndication) MarshalTo(b []byte) error {\n\tif s.Header.Payload != nil {\n\t\ts.Header.Payload = nil\n\t}\n\ts.Header.Payload = make([]byte, s.MarshalLen()-s.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := s.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(s.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := s.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(s.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range s.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(s.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\ts.Header.SetLength()\n\treturn s.Header.MarshalTo(b)\n}\n\n// ParseStopPagingIndication decodes given bytes as StopPagingIndication.\nfunc ParseStopPagingIndication(b []byte) (*StopPagingIndication, error) {\n\ts := &StopPagingIndication{}\n\tif err := s.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn s, nil\n}\n\n// UnmarshalBinary decodes given bytes as StopPagingIndication.\nfunc (s *StopPagingIndication) UnmarshalBinary(b []byte) error {\n\tvar err error\n\ts.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(s.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(s.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\ts.IMSI = i\n\t\tcase ie.PrivateExtension:\n\t\t\ts.PrivateExtension = i\n\t\tdefault:\n\t\t\ts.AdditionalIEs = append(s.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (s *StopPagingIndication) MarshalLen() int {\n\tl := s.Header.MarshalLen() - len(s.Header.Payload)\n\tif ie := s.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := s.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range s.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (s *StopPagingIndication) SetLength() {\n\ts.Header.Length = uint16(s.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (s *StopPagingIndication) MessageTypeName() string {\n\treturn \"Stop Paging Indication\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (s *StopPagingIndication) TEID() uint32 {\n\treturn s.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/stop-paging-indication_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes StopPagingIndication into bytes.\n//\n// Deprecated: use StopPagingIndication.Marshal instead.\nfunc (s *StopPagingIndication) Serialize() ([]byte, error) {\n\tlog.Println(\"StopPagingIndication.Serialize is deprecated. use StopPagingIndication.Marshal instead\")\n\treturn s.Marshal()\n}\n\n// SerializeTo serializes StopPagingIndication into bytes given as b.\n//\n// Deprecated: use StopPagingIndication.MarshalTo instead.\nfunc (s *StopPagingIndication) SerializeTo(b []byte) error {\n\tlog.Println(\"StopPagingIndication.SerializeTo is deprecated. use StopPagingIndication.MarshalTo instead\")\n\treturn s.MarshalTo(b)\n}\n\n// DecodeStopPagingIndication decodes bytes as StopPagingIndication.\n//\n// Deprecated: use ParseStopPagingIndication instead.\nfunc DecodeStopPagingIndication(b []byte) (*StopPagingIndication, error) {\n\tlog.Println(\"DecodeStopPagingIndication is deprecated. use ParseStopPagingIndication instead\")\n\treturn ParseStopPagingIndication(b)\n}\n\n// DecodeFromBytes decodes bytes as StopPagingIndication.\n//\n// Deprecated: use StopPagingIndication.UnmarshalBinary instead.\nfunc (s *StopPagingIndication) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"StopPagingIndication.DecodeFromBytes is deprecated. use StopPagingIndication.UnmarshalBinary instead\")\n\treturn s.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of StopPagingIndication.\n//\n// Deprecated: use StopPagingIndication.MarshalLen instead.\nfunc (s *StopPagingIndication) Len() int {\n\tlog.Println(\"StopPagingIndication.Len is deprecated. use StopPagingIndication.MarshalLen instead\")\n\treturn s.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/stop-paging-indication_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestStopPagingIndication(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/CauseOnly\",\n\t\t\tStructured: message.NewStopPagingIndication(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x49, 0x00, 0x14, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseStopPagingIndication(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/suspend-acknowledge.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// SuspendAcknowledge is a SuspendAcknowledge Header and its IEs above.\ntype SuspendAcknowledge struct {\n\t*Header\n\tCause            *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewSuspendAcknowledge creates a new SuspendAcknowledge.\nfunc NewSuspendAcknowledge(teid, seq uint32, ies ...*ie.IE) *SuspendAcknowledge {\n\tc := &SuspendAcknowledge{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeSuspendAcknowledge, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes SuspendAcknowledge into bytes.\nfunc (c *SuspendAcknowledge) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes SuspendAcknowledge into bytes.\nfunc (c *SuspendAcknowledge) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseSuspendAcknowledge decodes given bytes as SuspendAcknowledge.\nfunc ParseSuspendAcknowledge(b []byte) (*SuspendAcknowledge, error) {\n\tc := &SuspendAcknowledge{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as SuspendAcknowledge.\nfunc (c *SuspendAcknowledge) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *SuspendAcknowledge) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *SuspendAcknowledge) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *SuspendAcknowledge) MessageTypeName() string {\n\treturn \"Suspend Acknowledge\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *SuspendAcknowledge) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/suspend-acknowledge_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestSuspendAcknowledge(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewSuspendAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 163, 0x00, 14, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tDescription: \"With Private Extension\",\n\t\t\tStructured: message.NewSuspendAcknowledge(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewPrivateExtension(123, []byte{1, 2, 3, 4}),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 163, 0x00, 24, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// Private Extension\n\t\t\t\t0xff, 0x00, 0x06, 0x00, 0x00, 123, 1, 2, 3, 4,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseSuspendAcknowledge(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/suspend-notification.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// SuspendNotification is a SuspendNotification Header and its IEs above.\ntype SuspendNotification struct {\n\t*Header\n\tIMSI                   *ie.IE\n\tRAI                    *ie.IE\n\tLinkedEBI              *ie.IE\n\tPTMSI                  *ie.IE\n\tOriginatingNode        *ie.IE\n\tAddressForControlPlane *ie.IE\n\tUDPSourcePortNumber    *ie.IE\n\tHopCounter             *ie.IE\n\tSenderFTEIDC           *ie.IE\n\tPrivateExtension       *ie.IE\n\tAdditionalIEs          []*ie.IE\n}\n\n// NewSuspendNotification creates a new SuspendNotification.\nfunc NewSuspendNotification(teid, seq uint32, ies ...*ie.IE) *SuspendNotification {\n\tc := &SuspendNotification{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeSuspendNotification, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.RAI = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.PacketTMSI:\n\t\t\tc.PTMSI = i\n\t\tcase ie.NodeType:\n\t\t\tc.OriginatingNode = i\n\t\tcase ie.IPAddress:\n\t\t\tc.AddressForControlPlane = i\n\t\tcase ie.PortNumber:\n\t\t\tc.UDPSourcePortNumber = i\n\t\tcase ie.HopCounter:\n\t\t\tc.HopCounter = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.SenderFTEIDC = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes SuspendNotification into bytes.\nfunc (c *SuspendNotification) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes SuspendNotification into bytes.\nfunc (c *SuspendNotification) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.IMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.RAI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PTMSI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.OriginatingNode; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.AddressForControlPlane; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UDPSourcePortNumber; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HopCounter; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDC; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseSuspendNotification decodes given bytes as SuspendNotification.\nfunc ParseSuspendNotification(b []byte) (*SuspendNotification, error) {\n\tc := &SuspendNotification{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as SuspendNotification.\nfunc (c *SuspendNotification) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.IMSI:\n\t\t\tc.IMSI = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.RAI = i\n\t\tcase ie.PacketTMSI:\n\t\t\tc.PTMSI = i\n\t\tcase ie.EPSBearerID:\n\t\t\tc.LinkedEBI = i\n\t\tcase ie.NodeType:\n\t\t\tc.OriginatingNode = i\n\t\tcase ie.IPAddress:\n\t\t\tc.AddressForControlPlane = i\n\t\tcase ie.PortNumber:\n\t\t\tc.UDPSourcePortNumber = i\n\t\tcase ie.HopCounter:\n\t\t\tc.HopCounter = i\n\t\tcase ie.FullyQualifiedTEID:\n\t\t\tc.SenderFTEIDC = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *SuspendNotification) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\tif ie := c.IMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.RAI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PTMSI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.LinkedEBI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.OriginatingNode; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.AddressForControlPlane; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UDPSourcePortNumber; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HopCounter; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SenderFTEIDC; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *SuspendNotification) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *SuspendNotification) MessageTypeName() string {\n\treturn \"Suspend Notification\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *SuspendNotification) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/suspend-notification_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestSuspendNotification(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewSuspendNotification(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewIMSI(\"123451234567890\"),\n\t\t\t\tie.NewUserLocationInformationStruct(\n\t\t\t\t\tnil, nil, nil, ie.NewTAI(\"123\", \"45\", 0x0001),\n\t\t\t\t\tie.NewECGI(\"123\", \"45\", 0x00000101), nil, nil, nil,\n\t\t\t\t),\n\t\t\t\tie.NewEPSBearerID(5),\n\t\t\t\tie.NewPacketTMSI(0xdeadbeef),\n\t\t\t\tie.NewNodeType(gtpv2.NodeTypeMME),\n\t\t\t\tie.NewIPAddress(\"1.1.1.1\"),\n\t\t\t\tie.NewPortNumber(2123),\n\t\t\t\tie.NewHopCounter(1),\n\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS10MMEGTPC, 0xffffffff, \"1.1.1.1\", \"\"),\n\t\t\t\tie.NewPrivateExtension(123, []byte{1, 2, 3, 4}),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 162, 0x00, 97, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// IMSI\n\t\t\t\t0x01, 0x00, 0x08, 0x00, 0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0,\n\t\t\t\t// UserLocationInformation\n\t\t\t\t0x56, 0x00, 0x0d, 0x00, 0x18,\n\t\t\t\t0x21, 0xf3, 0x54, 0x00, 0x01,\n\t\t\t\t0x21, 0xf3, 0x54, 0x00, 0x00, 0x01, 0x01,\n\t\t\t\t// EPSBearerID\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t// PacketTMSI\n\t\t\t\t0x6f, 0x00, 0x04, 0x00, 0xde, 0xad, 0xbe, 0xef,\n\t\t\t\t// NodeType\n\t\t\t\t0x87, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// IPAddress\n\t\t\t\t0x4a, 0x00, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// PortNumber\n\t\t\t\t0x7e, 0x00, 0x02, 0x00, 0x08, 0x4b,\n\t\t\t\t// HopCounter\n\t\t\t\t0x71, 0x00, 0x01, 0x00, 0x01,\n\t\t\t\t// FullyQualifiedTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x8c, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01,\n\t\t\t\t// PrivateExtension\n\t\t\t\t0xff, 0x00, 0x06, 0x00, 0x00, 123, 1, 2, 3, 4,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tDescription: \"Erlang binary\",\n\t\t\tStructured: message.NewSuspendNotification(\n\t\t\t\t1024, 127,\n\t\t\t\tie.NewIPAddress(\"1.2.3.4\"),\n\t\t\t\tie.NewPortNumber(2345),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t0x48, 0xa2, 0x00, 0x16, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,\n\t\t\t\t0x7f, 0x00, 0x4a, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03, 0x04,\n\t\t\t\t0x7e, 0x00, 0x02, 0x00, 0x09, 0x29,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseSuspendNotification(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/update-bearer-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// UpdateBearerRequest is a UpdateBearerRequest Header and its IEs above.\ntype UpdateBearerRequest struct {\n\t*Header\n\tBearerContexts                []*ie.IE\n\tPTI                           *ie.IE\n\tPCO                           *ie.IE\n\tAPNAMBR                       *ie.IE\n\tChangeReportingAction         *ie.IE\n\tCSGInformationReportingAction *ie.IE\n\tHeNBInformationReporting      *ie.IE\n\tIndicationFlags               *ie.IE\n\tPGWFQCSID                     *ie.IE\n\tSGWFQCSID                     *ie.IE\n\tPresenceReportingAction       []*ie.IE\n\tPGWNodeLoadControlInformation *ie.IE\n\tPGWAPNLoadControlInformation  *ie.IE\n\tSGWNodeLoadControlInformation *ie.IE\n\tPGWOverloadControlInformation *ie.IE\n\tSGWOverloadControlInformation *ie.IE\n\tNBIFOMContainer               *ie.IE\n\tPrivateExtension              *ie.IE\n\tAdditionalIEs                 []*ie.IE\n}\n\n// NewUpdateBearerRequest creates a new UpdateBearerRequest.\nfunc NewUpdateBearerRequest(teid, seq uint32, ies ...*ie.IE) *UpdateBearerRequest {\n\tc := &UpdateBearerRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeUpdateBearerRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.ProcedureTransactionID:\n\t\t\tc.PTI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.APNAMBR = i\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tc.HeNBInformationReporting = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAction = append(c.PresenceReportingAction, i)\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes UpdateBearerRequest into bytes.\nfunc (c *UpdateBearerRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes UpdateBearerRequest into bytes.\nfunc (c *UpdateBearerRequest) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range c.BearerContexts {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PTI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.APNAMBR; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBInformationReporting; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAction {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWAPNLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeLoadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseUpdateBearerRequest decodes given bytes as UpdateBearerRequest.\nfunc ParseUpdateBearerRequest(b []byte) (*UpdateBearerRequest, error) {\n\tc := &UpdateBearerRequest{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as UpdateBearerRequest.\nfunc (c *UpdateBearerRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tswitch i.Type {\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.ProcedureTransactionID:\n\t\t\tc.PTI = i\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.AggregateMaximumBitRate:\n\t\t\tc.APNAMBR = i\n\t\tcase ie.ChangeReportingAction:\n\t\t\tc.ChangeReportingAction = i\n\t\tcase ie.CSGInformationReportingAction:\n\t\t\tc.CSGInformationReportingAction = i\n\t\tcase ie.HeNBInformationReporting:\n\t\t\tc.HeNBInformationReporting = i\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAction = append(c.PresenceReportingAction, i)\n\t\tcase ie.LoadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWNodeLoadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.PGWAPNLoadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.SGWNodeLoadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.PGWOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *UpdateBearerRequest) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tfor _, ie := range c.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PTI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.APNAMBR; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ChangeReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.CSGInformationReportingAction; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.HeNBInformationReporting; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWAPNLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWNodeLoadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *UpdateBearerRequest) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *UpdateBearerRequest) MessageTypeName() string {\n\treturn \"Update Bearer Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *UpdateBearerRequest) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/update-bearer-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestUpdateBearerRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewUpdateBearerRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, 0xffffffff, \"1.1.1.4\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x61, 0x00, 0x34, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x12, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x04,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdateBearerRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/update-bearer-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// UpdateBearerResponse is a UpdateBearerResponse Header and its IEs above.\ntype UpdateBearerResponse struct {\n\t*Header\n\tCause                              *ie.IE\n\tBearerContexts                     []*ie.IE\n\tPCO                                *ie.IE\n\tRecovery                           *ie.IE\n\tMMEFQCSID                          *ie.IE\n\tSGWFQCSID                          *ie.IE\n\tEPDGFQCSID                         *ie.IE\n\tTWANFQCSID                         *ie.IE\n\tIndicationFlags                    *ie.IE\n\tUETimeZone                         *ie.IE\n\tULI                                *ie.IE\n\tTWANIdentifier                     *ie.IE\n\tMMESGSNOverloadControlInformation  *ie.IE\n\tSGWOverloadControlInformation      *ie.IE\n\tPresenceReportingAreaAction        []*ie.IE\n\tMMESGSNIdentifier                  *ie.IE\n\tTWANePDGOverloadControlInformation *ie.IE\n\tWLANLocationInformation            *ie.IE\n\tWLANLocationTimeStamp              *ie.IE\n\tUELocalIPAddress                   *ie.IE\n\tUEUDPPort                          *ie.IE\n\tNBIFOMContainer                    *ie.IE\n\tUETCPPort                          *ie.IE\n\tPrivateExtension                   *ie.IE\n\tAdditionalIEs                      []*ie.IE\n}\n\n// NewUpdateBearerRequest creates a new UpdateBearerRequest.\nfunc NewUpdateBearerResponse(teid, seq uint32, ies ...*ie.IE) *UpdateBearerResponse {\n\tc := &UpdateBearerResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeUpdateBearerResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.ULI = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.UELocalIPAddress = i\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationTimeStamp = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tc.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tc.SetLength()\n\treturn c\n}\n\n// Marshal serializes UpdateBearerResponse into bytes.\nfunc (c *UpdateBearerResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, c.MarshalLen())\n\tif err := c.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes UpdateBearerResponse into bytes.\nfunc (c *UpdateBearerResponse) MarshalTo(b []byte) error {\n\tif c.Header.Payload != nil {\n\t\tc.Header.Payload = nil\n\t}\n\tc.Header.Payload = make([]byte, c.MarshalLen()-c.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := c.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNIdentifier; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.TWANePDGOverloadControlInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationInformation; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationTimeStamp; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UELocalIPAddress; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UEUDPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.UETCPPort; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(c.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(c.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tc.Header.SetLength()\n\treturn c.Header.MarshalTo(b)\n}\n\n// ParseUpdateBearerResponse decodes given bytes as UpdateBearerResponse.\nfunc ParseUpdateBearerResponse(b []byte) (*UpdateBearerResponse, error) {\n\tc := &UpdateBearerResponse{}\n\tif err := c.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n\n// UnmarshalBinary decodes given bytes as UpdateBearerResponse.\nfunc (c *UpdateBearerResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tc.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(c.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(c.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tc.Cause = i\n\t\tcase ie.BearerContext:\n\t\t\tc.BearerContexts = append(c.BearerContexts, i)\n\t\tcase ie.ProtocolConfigurationOptions:\n\t\t\tc.PCO = i\n\t\tcase ie.Recovery:\n\t\t\tc.Recovery = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWFQCSID = i\n\t\t\tcase 2:\n\t\t\t\tc.EPDGFQCSID = i\n\t\t\tcase 3:\n\t\t\t\tc.TWANFQCSID = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.Indication:\n\t\t\tc.IndicationFlags = i\n\t\tcase ie.UETimeZone:\n\t\t\tc.UETimeZone = i\n\t\tcase ie.UserLocationInformation:\n\t\t\tc.ULI = i\n\t\tcase ie.TWANIdentifier:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.TWANIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.OverloadControlInformation:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNOverloadControlInformation = i\n\t\t\tcase 1:\n\t\t\t\tc.SGWOverloadControlInformation = i\n\t\t\tcase 2:\n\t\t\t\tc.TWANePDGOverloadControlInformation = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PresenceReportingAreaAction:\n\t\t\tc.PresenceReportingAreaAction = append(c.PresenceReportingAreaAction, i)\n\t\tcase ie.IPAddress:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.MMESGSNIdentifier = i\n\t\t\tcase 1:\n\t\t\t\tc.UELocalIPAddress = i\n\t\t\t}\n\t\tcase ie.TWANIdentifierTimestamp:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 1:\n\t\t\t\tc.WLANLocationTimeStamp = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PortNumber:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tc.UEUDPPort = i\n\t\t\tcase 1:\n\t\t\t\tc.UETCPPort = i\n\t\t\tdefault:\n\t\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.FContainer:\n\t\t\tc.NBIFOMContainer = i\n\t\tcase ie.PrivateExtension:\n\t\t\tc.PrivateExtension = i\n\t\tdefault:\n\t\t\tc.AdditionalIEs = append(c.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (c *UpdateBearerResponse) MarshalLen() int {\n\tl := c.Header.MarshalLen() - len(c.Header.Payload)\n\n\tif ie := c.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.BearerContexts {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PCO; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.EPDGFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.IndicationFlags; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETimeZone; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.ULI; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.SGWOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tfor _, ie := range c.PresenceReportingAreaAction {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.MMESGSNIdentifier; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.TWANePDGOverloadControlInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationInformation; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.WLANLocationTimeStamp; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UELocalIPAddress; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UEUDPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.NBIFOMContainer; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.UETCPPort; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := c.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range c.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (c *UpdateBearerResponse) SetLength() {\n\tc.Header.Length = uint16(c.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (c *UpdateBearerResponse) MessageTypeName() string {\n\treturn \"Update Bearer Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (c *UpdateBearerResponse) TEID() uint32 {\n\treturn c.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/update-bearer-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestUpdateBearerResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewUpdateBearerResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\t\tie.NewEPSBearerID(0x05),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\t),\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewBearerContext(\n\t\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\t\tie.NewEPSBearerID(0x06),\n\t\t\t\t\tie.NewFullyQualifiedTEID(gtpv2.IFTypeS1USGWGTPU, 0xffffffff, \"1.1.1.3\", \"\"),\n\t\t\t\t),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x62, 0x00, 0x46, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// BearerContext 1\n\t\t\t\t0x5d, 0x00, 0x18, 0x00,\n\t\t\t\t//   Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x05,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t\t// BearerContext 2\n\t\t\t\t0x5d, 0x00, 0x18, 0x00,\n\t\t\t\t//   Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t//   EBI\n\t\t\t\t0x49, 0x00, 0x01, 0x00, 0x06,\n\t\t\t\t//   FTEID\n\t\t\t\t0x57, 0x00, 0x09, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdateBearerResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/update-pdn-connection-set-req.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// UpdatePDNConnectionSetRequest is a UpdatePDNConnectionSetRequest Header and its IEs above.\ntype UpdatePDNConnectionSetRequest struct {\n\t*Header\n\tMMEFQCSID        *ie.IE\n\tSGWFQCSID        *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewUpdatePDNConnectionSetRequest creates a new UpdatePDNConnectionSetRequest.\nfunc NewUpdatePDNConnectionSetRequest(teid, seq uint32, ies ...*ie.IE) *UpdatePDNConnectionSetRequest {\n\tm := &UpdatePDNConnectionSetRequest{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeUpdatePDNConnectionSetRequest, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal serializes UpdatePDNConnectionSetRequest into bytes.\nfunc (m *UpdatePDNConnectionSetRequest) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes UpdatePDNConnectionSetRequest into bytes.\nfunc (m *UpdatePDNConnectionSetRequest) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.MMEFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseUpdatePDNConnectionSetRequest decodes given bytes as UpdatePDNConnectionSetRequest.\nfunc ParseUpdatePDNConnectionSetRequest(b []byte) (*UpdatePDNConnectionSetRequest, error) {\n\tm := &UpdatePDNConnectionSetRequest{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given bytes as UpdatePDNConnectionSetRequest.\nfunc (m *UpdatePDNConnectionSetRequest) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tswitch i.Instance() {\n\t\t\tcase 0:\n\t\t\t\tm.MMEFQCSID = i\n\t\t\tcase 1:\n\t\t\t\tm.SGWFQCSID = i\n\t\t\tdefault:\n\t\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t\t}\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (m *UpdatePDNConnectionSetRequest) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.MMEFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.SGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *UpdatePDNConnectionSetRequest) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *UpdatePDNConnectionSetRequest) MessageTypeName() string {\n\treturn \"Update PDN Connection Set Request\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *UpdatePDNConnectionSetRequest) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/update-pdn-connection-set-req_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestUpdatePDNConnectionSetRequest(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewUpdatePDNConnectionSetRequest(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1),\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1).WithInstance(1),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xc8, 0x00, 0x1e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// MME-FQ-CSID\n\t\t\t\t0x84, 0x00, 0x07, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,\n\t\t\t\t// SGW-FQ-CSID\n\t\t\t\t0x84, 0x00, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdatePDNConnectionSetRequest(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/update-pdn-connection-set-res.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// UpdatePDNConnectionSetResponse is a UpdatePDNConnectionSetResponse Header and its IEs above.\ntype UpdatePDNConnectionSetResponse struct {\n\t*Header\n\tCause            *ie.IE\n\tPGWFQCSID        *ie.IE\n\tRecovery         *ie.IE\n\tPrivateExtension *ie.IE\n\tAdditionalIEs    []*ie.IE\n}\n\n// NewUpdatePDNConnectionSetResponse creates a new UpdatePDNConnectionSetResponse.\nfunc NewUpdatePDNConnectionSetResponse(teid, seq uint32, ies ...*ie.IE) *UpdatePDNConnectionSetResponse {\n\tm := &UpdatePDNConnectionSetResponse{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeUpdatePDNConnectionSetResponse, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ies {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tm.PGWFQCSID = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\tm.SetLength()\n\treturn m\n}\n\n// Marshal returns the byte sequence generated from a UpdatePDNConnectionSetResponse.\nfunc (m *UpdatePDNConnectionSetResponse) Marshal() ([]byte, error) {\n\tb := make([]byte, m.MarshalLen())\n\tif err := m.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b, nil\n}\n\n// MarshalTo puts the byte sequence in the byte array given as b.\nfunc (m *UpdatePDNConnectionSetResponse) MarshalTo(b []byte) error {\n\tif m.Header.Payload != nil {\n\t\tm.Header.Payload = nil\n\t}\n\tm.Header.Payload = make([]byte, m.MarshalLen()-m.Header.MarshalLen())\n\n\toffset := 0\n\tif ie := m.Cause; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PGWFQCSID; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(m.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tm.Header.SetLength()\n\treturn m.Header.MarshalTo(b)\n}\n\n// ParseUpdatePDNConnectionSetResponse decodes a given byte sequence as a UpdatePDNConnectionSetResponse.\nfunc ParseUpdatePDNConnectionSetResponse(b []byte) (*UpdatePDNConnectionSetResponse, error) {\n\tm := &UpdatePDNConnectionSetResponse{}\n\tif err := m.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\n// UnmarshalBinary decodes given byte sequence as UpdatePDNConnectionSetResponse.\nfunc (m *UpdatePDNConnectionSetResponse) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tm.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(m.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(m.Header.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch i.Type {\n\t\tcase ie.Cause:\n\t\t\tm.Cause = i\n\t\tcase ie.FullyQualifiedCSID:\n\t\t\tm.PGWFQCSID = i\n\t\tcase ie.Recovery:\n\t\t\tm.Recovery = i\n\t\tcase ie.PrivateExtension:\n\t\t\tm.PrivateExtension = i\n\t\tdefault:\n\t\t\tm.AdditionalIEs = append(m.AdditionalIEs, i)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length of Data.\nfunc (m *UpdatePDNConnectionSetResponse) MarshalLen() int {\n\tl := m.Header.MarshalLen() - len(m.Header.Payload)\n\n\tif ie := m.Cause; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PGWFQCSID; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.Recovery; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\tif ie := m.PrivateExtension; ie != nil {\n\t\tl += ie.MarshalLen()\n\t}\n\n\tfor _, ie := range m.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length field.\nfunc (m *UpdatePDNConnectionSetResponse) SetLength() {\n\tm.Header.Length = uint16(m.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (m *UpdatePDNConnectionSetResponse) MessageTypeName() string {\n\treturn \"Update PDN Connection Set Response\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (m *UpdatePDNConnectionSetResponse) TEID() uint32 {\n\treturn m.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/update-pdn-connection-set-res_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestUpdatePDNConnectionSetResponse(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal\",\n\t\t\tStructured: message.NewUpdatePDNConnectionSetResponse(\n\t\t\t\ttestutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq,\n\t\t\t\tie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil),\n\t\t\t\tie.NewFullyQualifiedCSID(\"1.1.1.1\", 1),\n\t\t\t\tie.NewRecovery(0xff),\n\t\t\t),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0xc9, 0x00, 0x1e, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t\t// Cause\n\t\t\t\t0x02, 0x00, 0x02, 0x00, 0x10, 0x00,\n\t\t\t\t// PGW-FQ-CSID\n\t\t\t\t0x84, 0x00, 0x07, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,\n\t\t\t\t// Recovery\n\t\t\t\t0x03, 0x00, 0x01, 0x00, 0xff,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseUpdatePDNConnectionSetResponse(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/message/version-not-supported.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reservev.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport (\n\t\"errors\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/ie\"\n)\n\n// VersionNotSupportedIndication is a VersionNotSupportedIndication Header and its IEs above.\ntype VersionNotSupportedIndication struct {\n\t*Header\n\tAdditionalIEs []*ie.IE\n}\n\n// NewVersionNotSupportedIndication creates a new VersionNotSupportedIndication.\nfunc NewVersionNotSupportedIndication(teid, seq uint32, ie ...*ie.IE) *VersionNotSupportedIndication {\n\tv := &VersionNotSupportedIndication{\n\t\tHeader: NewHeader(\n\t\t\tNewHeaderFlags(2, 0, 1),\n\t\t\tMsgTypeVersionNotSupportedIndication, teid, seq, nil,\n\t\t),\n\t}\n\n\tfor _, i := range ie {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tv.AdditionalIEs = append(v.AdditionalIEs, i)\n\t}\n\n\tv.SetLength()\n\treturn v\n}\n\n// Marshal serializes VersionNotSupportedIndication into bytes.\nfunc (v *VersionNotSupportedIndication) Marshal() ([]byte, error) {\n\tb := make([]byte, v.MarshalLen())\n\tif err := v.MarshalTo(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// MarshalTo serializes VersionNotSupportedIndication into bytes.\nfunc (v *VersionNotSupportedIndication) MarshalTo(b []byte) error {\n\tif v.Header.Payload != nil {\n\t\tv.Header.Payload = nil\n\t}\n\tv.Header.Payload = make([]byte, v.MarshalLen()-v.Header.MarshalLen())\n\n\toffset := 0\n\tfor _, ie := range v.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif err := ie.MarshalTo(v.Header.Payload[offset:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t\toffset += ie.MarshalLen()\n\t}\n\n\tv.Header.SetLength()\n\treturn v.Header.MarshalTo(b)\n}\n\n// ParseVersionNotSupportedIndication decodes given bytes as VersionNotSupportedIndication.\nfunc ParseVersionNotSupportedIndication(b []byte) (*VersionNotSupportedIndication, error) {\n\tv := &VersionNotSupportedIndication{}\n\tif err := v.UnmarshalBinary(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn v, nil\n}\n\n// UnmarshalBinary decodes given bytes as VersionNotSupportedIndication.\nfunc (v *VersionNotSupportedIndication) UnmarshalBinary(b []byte) error {\n\tvar err error\n\tv.Header, err = ParseHeader(b)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(v.Header.Payload) < 2 {\n\t\treturn nil\n\t}\n\n\tdecodedIEs, err := ie.ParseMultiIEs(v.Header.Payload)\n\tif err != nil {\n\t\tif errors.Is(err, ErrTooShortToParse) {\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\n\tfor _, i := range decodedIEs {\n\t\tif i == nil {\n\t\t\tcontinue\n\t\t}\n\t\tv.AdditionalIEs = append(v.AdditionalIEs, i)\n\t}\n\n\treturn nil\n}\n\n// MarshalLen returns the serial length in int.\nfunc (v *VersionNotSupportedIndication) MarshalLen() int {\n\tl := v.Header.MarshalLen() - len(v.Header.Payload)\n\tfor _, ie := range v.AdditionalIEs {\n\t\tif ie == nil {\n\t\t\tcontinue\n\t\t}\n\t\tl += ie.MarshalLen()\n\t}\n\treturn l\n}\n\n// SetLength sets the length in Length fielv.\nfunc (v *VersionNotSupportedIndication) SetLength() {\n\tv.Header.Length = uint16(v.MarshalLen() - 4)\n}\n\n// MessageTypeName returns the name of protocol.\nfunc (v *VersionNotSupportedIndication) MessageTypeName() string {\n\treturn \"Version Not Supported Indication\"\n}\n\n// TEID returns the TEID in uint32.\nfunc (v *VersionNotSupportedIndication) TEID() uint32 {\n\treturn v.Header.teid()\n}\n"
  },
  {
    "path": "gtpv2/message/version-not-supported_deprecated.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message\n\nimport \"log\"\n\n// Serialize serializes VersionNotSupportedIndication into bytes.\n//\n// Deprecated: use VersionNotSupportedIndication.Marshal instead.\nfunc (v *VersionNotSupportedIndication) Serialize() ([]byte, error) {\n\tlog.Println(\"VersionNotSupportedIndication.Serialize is deprecated. use VersionNotSupportedIndication.Marshal instead\")\n\treturn v.Marshal()\n}\n\n// SerializeTo serializes VersionNotSupportedIndication into bytes given as b.\n//\n// Deprecated: use VersionNotSupportedIndication.MarshalTo instead.\nfunc (v *VersionNotSupportedIndication) SerializeTo(b []byte) error {\n\tlog.Println(\"VersionNotSupportedIndication.SerializeTo is deprecated. use VersionNotSupportedIndication.MarshalTo instead\")\n\treturn v.MarshalTo(b)\n}\n\n// DecodeVersionNotSupportedIndication decodes bytes as VersionNotSupportedIndication.\n//\n// Deprecated: use ParseVersionNotSupportedIndication instead.\nfunc DecodeVersionNotSupportedIndication(b []byte) (*VersionNotSupportedIndication, error) {\n\tlog.Println(\"DecodeVersionNotSupportedIndication is deprecated. use ParseVersionNotSupportedIndication instead\")\n\treturn ParseVersionNotSupportedIndication(b)\n}\n\n// DecodeFromBytes decodes bytes as VersionNotSupportedIndication.\n//\n// Deprecated: use VersionNotSupportedIndication.UnmarshalBinary instead.\nfunc (v *VersionNotSupportedIndication) DecodeFromBytes(b []byte) error {\n\tlog.Println(\"VersionNotSupportedIndication.DecodeFromBytes is deprecated. use VersionNotSupportedIndication.UnmarshalBinary instead\")\n\treturn v.UnmarshalBinary(b)\n}\n\n// Len returns the actual length of VersionNotSupportedIndication.\n//\n// Deprecated: use VersionNotSupportedIndication.MarshalLen instead.\nfunc (v *VersionNotSupportedIndication) Len() int {\n\tlog.Println(\"VersionNotSupportedIndication.Len is deprecated. use VersionNotSupportedIndication.MarshalLen instead\")\n\treturn v.MarshalLen()\n}\n"
  },
  {
    "path": "gtpv2/message/version-not-supported_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage message_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/testutils\"\n)\n\nfunc TestVersionNotSupportedIndication(t *testing.T) {\n\tcases := []testutils.TestCase{\n\t\t{\n\t\t\tDescription: \"Normal/CauseOnly\",\n\t\t\tStructured:  message.NewVersionNotSupportedIndication(testutils.TestBearerInfo.TEID, testutils.TestBearerInfo.Seq),\n\t\t\tSerialized: []byte{\n\t\t\t\t// Header\n\t\t\t\t0x48, 0x03, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x01, 0x00,\n\t\t\t},\n\t\t},\n\t}\n\n\ttestutils.Run(t, cases, func(b []byte) (testutils.Serializable, error) {\n\t\tv, err := message.ParseVersionNotSupportedIndication(b)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.Payload = nil\n\t\treturn v, nil\n\t})\n}\n"
  },
  {
    "path": "gtpv2/session.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage gtpv2\n\nimport (\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// Location is a subscriber's location.\ntype Location struct {\n\tMCC, MNC               string\n\tRATType                uint8\n\tLAC, CI, SAI, RAI, TAI uint16\n\tECI, MeNBI, EMeNBI     uint32\n}\n\n// Subscriber is a subscriber that belongs to a GTPv2 session.\ntype Subscriber struct {\n\tIMSI, MSISDN, IMEI string\n\t*Location\n}\n\n// Session is a GTPv2 Session.\ntype Session struct {\n\tmu       sync.Mutex\n\tisActive bool\n\t*teidMap\n\t*bearerMap\n\n\t// channel to store message passed by other Sessions\n\tmsgQueue chan message.Message\n\n\t// peerAddr is a net.Addr of the peer associated with Session.\n\t// To avoid calling String() many times, peerAddrString is set when NewSession\n\t// and UpdatePeerAddr is called.\n\tpeerAddr       net.Addr\n\tpeerAddrString string\n\n\t// Subscriber is a Subscriber associated with Session.\n\t*Subscriber\n}\n\n// NewSession creates a new Session with subscriber information.\n//\n// This is expected to be used by server-like nodes. Otherwise, use CreateSession(),\n// which sends Create Session Request and returns a new Session.\nfunc NewSession(peerAddr net.Addr, sub *Subscriber) *Session {\n\ts := &Session{\n\t\tmu:             sync.Mutex{},\n\t\tpeerAddr:       peerAddr,\n\t\tpeerAddrString: peerAddr.String(),\n\t\tteidMap:        newTeidMap(),\n\t\tbearerMap:      newBearerMap(\"default\", &Bearer{QoSProfile: &QoSProfile{}}),\n\t\tSubscriber:     sub,\n\t\tmsgQueue:       make(chan message.Message, 1000),\n\t}\n\n\treturn s\n}\n\n// Activate marks a Session active.\nfunc (s *Session) Activate() error {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif s.IMSI == \"\" {\n\t\treturn &RequiredParameterMissingError{\"IMSI\", \"Session must have IMSI set\"}\n\t}\n\n\ts.isActive = true\n\treturn nil\n}\n\n// Deactivate marks a Session inactive.\nfunc (s *Session) Deactivate() error {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\ts.isActive = false\n\treturn nil\n}\n\n// IsActive reports whether a Session is active or not.\nfunc (s *Session) IsActive() bool {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\treturn s.isActive\n}\n\n// PeerAddr returns the address of the peer node associated with Session.\nfunc (s *Session) PeerAddr() net.Addr {\n\treturn s.peerAddr\n}\n\n// UpdatePeerAddr updates the address of the peer node associated with Session.\nfunc (s *Session) UpdatePeerAddr(peer net.Addr) {\n\ts.peerAddr = peer\n\ts.peerAddrString = peer.String()\n}\n\n// AddTEID adds TEID to session with InterfaceType.\n//\n// This is used to keep TEIDs of any interface types that may be used later,\n// including the ones that are assigned to U-Plane.\n//\n// For incoming TEID of local interface type, (*Conn).RegisterSession does that\n// instead of users but it is safe to call it.\nfunc (s *Session) AddTEID(ifType uint8, teid uint32) {\n\ts.teidMap.store(ifType, teid)\n}\n\n// GetTEID returns TEID associated with InterfaceType given.\nfunc (s *Session) GetTEID(ifType uint8) (uint32, error) {\n\tif teid, ok := s.teidMap.load(ifType); ok {\n\t\treturn teid, nil\n\t}\n\treturn 0, ErrTEIDNotFound\n}\n\n// PassMessageTo passes the message (typically \"triggerred message\") to the session\n// expecting to receive it.\n//\n// If the message queue of s is full, it waits for certain period of time specified\n// by timeout. It discards the msg and returns error if expired.\n// The default queue size of a Session is 1000 and it cannot be configured in the\n// current implementation.\nfunc PassMessageTo(s *Session, msg message.Message, timeout time.Duration) error {\n\tselect {\n\tcase s.msgQueue <- msg:\n\t\treturn nil\n\tcase <-time.After(timeout):\n\t\treturn ErrTimeout\n\t}\n}\n\n// WaitMessage waits for a message to come from other Session.\n//\n// It waits for certain period of time specified by timeout, and returns the message\n// if seq matches the SequenceNumber of message. Otherwise it returns error immediately.\nfunc (s *Session) WaitMessage(seq uint32, timeout time.Duration) (message.Message, error) {\n\tselect {\n\tcase msg, ok := <-s.msgQueue:\n\t\tif !ok {\n\t\t\treturn nil, &InvalidSessionError{s.IMSI}\n\t\t}\n\n\t\tif seqGot := msg.Sequence(); seqGot != seq {\n\t\t\treturn nil, &InvalidSequenceError{seqGot}\n\t\t}\n\t\treturn msg, nil\n\tcase <-time.After(timeout):\n\t\treturn nil, ErrTimeout\n\t}\n}\n\n// AddBearer adds a Bearer to Session with arbitrary name given.\n//\n// In the single-bearer environment it is not used, as a bearer named \"default\" is\n// always available after created a Session.\nfunc (s *Session) AddBearer(name string, br *Bearer) {\n\ts.bearerMap.store(name, br)\n}\n\n// RemoveBearer removes a Bearer looked up by name.\nfunc (s *Session) RemoveBearer(name string) {\n\ts.bearerMap.delete(name)\n}\n\n// RemoveBearerByEBI removes a Bearer looked up by name.\nfunc (s *Session) RemoveBearerByEBI(ebi uint8) {\n\tname, err := s.LookupBearerNameByEBI(ebi)\n\tif err != nil {\n\t\treturn\n\t}\n\ts.bearerMap.delete(name)\n}\n\n// GetDefaultBearer returns the default bearer.\nfunc (s *Session) GetDefaultBearer() *Bearer {\n\t// it is not expected that the default bearer cannot be found.\n\tbearer, ok := s.bearerMap.load(\"default\")\n\tif !ok {\n\t\treturn nil\n\t}\n\n\treturn bearer\n}\n\n// SetDefaultBearer sets given bearer as the default bearer.\nfunc (s *Session) SetDefaultBearer(bearer *Bearer) {\n\t// it is not expected that the default bearer cannot be found.\n\ts.bearerMap.store(\"default\", bearer)\n}\n\n// LookupBearerByName looks up Bearer registered in Session by name.\nfunc (s *Session) LookupBearerByName(name string) (*Bearer, error) {\n\tif br, ok := s.bearerMap.load(name); ok {\n\t\treturn br, nil\n\t}\n\n\treturn nil, &BearerNotFoundError{IMSI: s.IMSI}\n}\n\n// LookupBearerByEBI looks up Bearer registered in Session by EBI.\nfunc (s *Session) LookupBearerByEBI(ebi uint8) (*Bearer, error) {\n\tvar bearer *Bearer\n\ts.bearerMap.rangeWithFunc(func(name, br interface{}) bool {\n\t\tb := br.(*Bearer)\n\t\tif ebi == b.EBI {\n\t\t\tbearer = b\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\tif bearer == nil {\n\t\treturn nil, &BearerNotFoundError{IMSI: s.IMSI}\n\n\t}\n\treturn bearer, nil\n}\n\n// LookupBearerNameByEBI looks up name of Bearer by EBI and returns\n// its name.\nfunc (s *Session) LookupBearerNameByEBI(ebi uint8) (string, error) {\n\tvar name string\n\ts.bearerMap.rangeWithFunc(func(n, br interface{}) bool {\n\t\tbearer := br.(*Bearer)\n\t\tif ebi == bearer.EBI {\n\t\t\tname = n.(string)\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\tif name == \"\" {\n\t\treturn \"\", &BearerNotFoundError{IMSI: s.IMSI}\n\n\t}\n\treturn name, nil\n}\n\n// LookupEBIByName returns EBI associated with name.\n//\n// If no EBI found, it returns 0(=invalid value for EBI).\nfunc (s *Session) LookupEBIByName(name string) uint8 {\n\tif br, ok := s.bearerMap.load(name); ok {\n\t\treturn br.EBI\n\t}\n\n\treturn 0\n}\n\n// LookupEBIByTEID returns EBI associated with TEID.\n//\n// If no EBI found, it returns 0(=invalid value for EBI).\nfunc (s *Session) LookupEBIByTEID(teid uint32) uint8 {\n\tvar ebi uint8\n\ts.bearerMap.rangeWithFunc(func(name, bearer interface{}) bool {\n\t\tbr := bearer.(*Bearer)\n\t\tif teid == br.teidIn || teid == br.teidOut {\n\t\t\tebi = br.EBI\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\treturn ebi\n}\n\ntype teidMap struct {\n\tsyncMap sync.Map\n}\n\nfunc newTeidMap() *teidMap {\n\treturn &teidMap{}\n}\n\nfunc (t *teidMap) store(ifType uint8, teid uint32) {\n\tt.syncMap.Store(ifType, teid)\n}\n\nfunc (t *teidMap) load(ifType uint8) (uint32, bool) {\n\tteid, ok := t.syncMap.Load(ifType)\n\tif !ok {\n\t\treturn 0, false\n\t}\n\n\treturn teid.(uint32), true\n}\n\ntype bearerMap struct {\n\tsyncMap sync.Map\n}\n\nfunc newBearerMap(name string, bearer *Bearer) *bearerMap {\n\tb := &bearerMap{}\n\tb.store(name, bearer)\n\n\treturn b\n}\nfunc (b *bearerMap) store(name string, bearer *Bearer) {\n\tb.syncMap.Store(name, bearer)\n}\n\nfunc (b *bearerMap) load(name string) (*Bearer, bool) {\n\tbearer, ok := b.syncMap.Load(name)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\n\treturn bearer.(*Bearer), true\n}\n\nfunc (b *bearerMap) delete(name string) {\n\tb.syncMap.Delete(name)\n}\n\nfunc (b *bearerMap) rangeWithFunc(fn func(name, bearer interface{}) bool) {\n\tb.syncMap.Range(fn)\n}\n\n// Bearers returns all the bearers registered in Session.\nfunc (s *Session) Bearers() []*Bearer {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tvar bs []*Bearer\n\ts.bearerMap.rangeWithFunc(func(k, v interface{}) bool {\n\t\tbs = append(bs, v.(*Bearer))\n\t\treturn true\n\t})\n\n\treturn bs\n}\n\n// BearerCount returns the number of bearers registered in Session.\nfunc (s *Session) BearerCount() int {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tvar count int\n\ts.bearerMap.rangeWithFunc(func(k, v interface{}) bool {\n\t\tcount++\n\t\treturn true\n\t})\n\n\treturn count\n}\n"
  },
  {
    "path": "gtpv2/testutils/testutils.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package testutils is an internal package to be used for unit tests. Don't use this.\npackage testutils\n\nimport (\n\t\"testing\"\n\n\t\"github.com/pascaldekloe/goe/verify\"\n\t\"github.com/wmnsk/go-gtp/gtpv2/message\"\n)\n\n// Serializable is just for testing gtpv2.Messages. Don't use this.\ntype Serializable interface {\n\tMarshal() ([]byte, error)\n\tMarshalLen() int\n}\n\n// TestCase is just for testing gtpv2.Messages. Don't use this.\ntype TestCase struct {\n\tDescription string\n\tStructured  Serializable\n\tSerialized  []byte\n}\n\n// ParseFunc is just for testing gtpv2.Messages. Don't use this.\ntype ParseFunc func([]byte) (Serializable, error)\n\n// TestBearerInfo is just for testing gtpv2.Messages. Don't use this.\nvar TestBearerInfo = struct{ TEID, Seq uint32 }{0x11223344, 0x00000001}\n\n// Run is just for testing gtpv2.Messages. Don't use this.\nfunc Run(t *testing.T, cases []TestCase, decode ParseFunc) {\n\tt.Helper()\n\n\tfor _, c := range cases {\n\t\tt.Run(c.Description, func(t *testing.T) {\n\t\t\tt.Run(\"Parse\", func(t *testing.T) {\n\t\t\t\tv, err := decode(c.Serialized)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := v, c.Structured; !verify.Values(t, \"\", got, want) {\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Marshal\", func(t *testing.T) {\n\t\t\t\tb, err := c.Structured.Marshal()\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := b, c.Serialized; !verify.Values(t, \"\", got, want) {\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Len\", func(t *testing.T) {\n\t\t\t\tif got, want := c.Structured.MarshalLen(), len(c.Serialized); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Interface\", func(t *testing.T) {\n\t\t\t\t// Ignore *Header and Generic in this tests.\n\t\t\t\tif _, ok := c.Structured.(*message.Header); ok {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif _, ok := c.Structured.(*message.Generic); ok {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tdecoded, err := message.Parse(c.Serialized)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif got, want := decoded.Version(), c.Structured.(message.Message).Version(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.MessageType(), c.Structured.(message.Message).MessageType(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.MessageTypeName(), c.Structured.(message.Message).MessageTypeName(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.TEID(), c.Structured.(message.Message).TEID(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t\tif got, want := decoded.Sequence(), c.Structured.(message.Message).Sequence(); got != want {\n\t\t\t\t\tt.Fatalf(\"got %v want %v\", got, want)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "utils/utils.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\n// Package utils provides some utilities which might be useful specifically for GTP(or other telco protocols).\npackage utils\n\nimport (\n\t\"encoding/binary\"\n\t\"encoding/hex\"\n\t\"strings\"\n)\n\n// StrToSwappedBytes returns swapped bits from a byte.\n// It is used for some values where some values are represented in swapped format.\n//\n// The second parameter is the hex character(0-f) to fill the last digit when\n// handling a odd number. \"f\" is used In most cases.\nfunc StrToSwappedBytes(s, filler string) ([]byte, error) {\n\tvar raw []byte\n\tvar err error\n\tif len(s)%2 == 0 {\n\t\traw, err = hex.DecodeString(s)\n\t} else {\n\t\traw, err = hex.DecodeString(s + filler)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn swap(raw), nil\n}\n\n// SwappedBytesToStr decodes raw swapped bytes into string.\n// It is used for some values where some values are represented in swapped format.\n//\n// The second parameter is to decide whether to cut the last digit or not.\nfunc SwappedBytesToStr(raw []byte, cutLastDigit bool) string {\n\tif len(raw) == 0 {\n\t\treturn \"\"\n\t}\n\n\ts := hex.EncodeToString(swap(raw))\n\tif cutLastDigit {\n\t\ts = s[:len(s)-1]\n\t}\n\n\treturn s\n}\n\nfunc swap(raw []byte) []byte {\n\tswapped := make([]byte, len(raw))\n\tfor n := range raw {\n\t\tt := ((raw[n] >> 4) & 0xf) + ((raw[n] << 4) & 0xf0)\n\t\tswapped[n] = t\n\t}\n\treturn swapped\n}\n\n// Uint24To32 converts 24bits-length []byte value into the uint32 with 8bits of zeros as prefix.\n// This function is used for the fields with 3 octets.\nfunc Uint24To32(b []byte) uint32 {\n\tif len(b) != 3 {\n\t\treturn 0\n\t}\n\treturn uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])\n}\n\n// Uint32To24 converts the uint32 value into 24bits-length []byte. The values in 25-32 bit are cut off.\n// This function is used for the fields with 3 octets.\nfunc Uint32To24(n uint32) []byte {\n\treturn []byte{uint8(n >> 16), uint8(n >> 8), uint8(n)}\n}\n\n// Uint40To64 converts 40bits-length []byte value into the uint64 with 8bits of zeros as prefix.\n// This function is used for the fields with 3 octets.\nfunc Uint40To64(b []byte) uint64 {\n\tif len(b) != 5 {\n\t\treturn 0\n\t}\n\treturn uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4])\n}\n\n// Uint64To40 converts the uint64 value into 40bits-length []byte. The values in 25-64 bit are cut off.\n// This function is used for the fields with 3 octets.\nfunc Uint64To40(n uint64) []byte {\n\treturn []byte{uint8(n >> 32), uint8(n >> 24), uint8(n >> 16), uint8(n >> 8), uint8(n)}\n}\n\n// EncodePLMN encodes MCC and MNC as BCD-encoded bytes.\nfunc EncodePLMN(mcc, mnc string) ([]byte, error) {\n\tc, err := StrToSwappedBytes(mcc, \"f\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tn, err := StrToSwappedBytes(mnc, \"f\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// 2-digit\n\tif len(mnc) == 2 {\n\t\treturn append(c, n...), nil\n\t}\n\n\t// 3-digit\n\tb := make([]byte, 3)\n\tb[0] = c[0]\n\tb[1] = (c[1] & 0x0f) | (n[1] << 4 & 0xf0)\n\tb[2] = n[0]\n\n\treturn b, nil\n}\n\n// DecodeMCC decodes BCD-encoded MCC as it occurs in CGI/SAI/RAI.\nfunc DecodeMNC(b []byte) string {\n\traw := hex.EncodeToString(b)\n\tif raw[0] == 'f' {\n\t\treturn string([]byte{raw[3], raw[2]})\n\t}\n\treturn string([]byte{raw[3], raw[2], raw[0]})\n}\n\n// DecodeMNC decodes BCD-encoded MNC as it occurs in CGI/SAI/RAI\nfunc DecodeMCC(b []byte) string {\n\traw := hex.EncodeToString(b)\n\treturn string([]byte{raw[1], raw[0], raw[3]})\n}\n\n// DecodePLMN decodes BCD-encoded bytes into MCC and MNC.\nfunc DecodePLMN(b []byte) (mcc, mnc string, err error) {\n\tmcc = DecodeMCC(b[0:2])\n\tmnc = DecodeMNC(b[1:3])\n\treturn\n}\n\n// ParseECI decodes ECI uint32 into e-NodeB ID and Cell ID.\nfunc ParseECI(eci uint32) (enbID uint32, cellID uint8, err error) {\n\tbuf := make([]byte, 4)\n\tbinary.BigEndian.PutUint32(buf, eci)\n\tcellID = buf[3]\n\tenbID = binary.BigEndian.Uint32([]byte{0, buf[0], buf[1], buf[2]})\n\treturn\n}\n\n// EncodeFQDN encodes the given string as the Name Syntax defined\n// in RFC 2181, RFC 1035 and RFC 1123.\nfunc EncodeFQDN(fqdn string) []byte {\n\tb := make([]byte, len(fqdn)+1)\n\n\tvar offset = 0\n\tfor _, label := range strings.Split(fqdn, \".\") {\n\t\tl := len(label)\n\t\tb[offset] = uint8(l)\n\t\tcopy(b[offset+1:], label)\n\t\toffset += l + 1\n\t}\n\n\treturn b\n}\n\n// DecodeFQDN decodes the given Name Syntax-encoded []byte as a string.\nfunc DecodeFQDN(b []byte) string {\n\tvar (\n\t\tfqdn   []string\n\t\toffset int\n\t)\n\n\tmax := len(b)\n\tfor {\n\t\tif offset >= max {\n\t\t\tbreak\n\t\t}\n\t\tl := int(b[offset])\n\t\tif offset+l+1 > max {\n\t\t\tbreak\n\t\t}\n\t\tfqdn = append(fqdn, string(b[offset+1:offset+l+1]))\n\t\toffset += l + 1\n\t}\n\n\treturn strings.Join(fqdn, \".\")\n}\n"
  },
  {
    "path": "utils/utils_test.go",
    "content": "// Copyright 2019-2024 go-gtp authors. All rights reserved.\n// Use of this source code is governed by a MIT-style license that can be\n// found in the LICENSE file.\n\npackage utils_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/wmnsk/go-gtp/utils\"\n)\n\nfunc TestBCDEncoding(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tstr         string\n\t\tbytes       []byte\n\t}{\n\t\t{\n\t\t\t\"imsi\",\n\t\t\t\"123451234567890\",\n\t\t\t[]byte{0x21, 0x43, 0x15, 0x32, 0x54, 0x76, 0x98, 0xf0},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"Str2Bytes/\"+c.description, func(t *testing.T) {\n\t\t\tswapped, err := utils.StrToSwappedBytes(c.str, \"f\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(swapped, c.bytes); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"Bytes2Str/\"+c.description, func(t *testing.T) {\n\t\t\tstr := utils.SwappedBytesToStr(c.bytes, true)\n\n\t\t\tif diff := cmp.Diff(str, c.str); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestUint32And24(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tu24         []byte\n\t\tu32         uint32\n\t}{\n\t\t{\n\t\t\t\"Normal\",\n\t\t\t[]byte{0xff, 0xff, 0xff},\n\t\t\t0x00ffffff,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"24To32\"+c.description, func(t *testing.T) {\n\t\t\tconverted := utils.Uint24To32(c.u24)\n\n\t\t\tif diff := cmp.Diff(converted, c.u32); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"32To24\"+c.description, func(t *testing.T) {\n\t\t\tconverted := utils.Uint32To24(c.u32)\n\n\t\t\tif diff := cmp.Diff(converted, c.u24); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestUint64And40(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tu40         []byte\n\t\tu64         uint64\n\t}{\n\t\t{\n\t\t\t\"Normal\",\n\t\t\t[]byte{0xff, 0xff, 0xff, 0xff, 0xff},\n\t\t\t0x000000ffffffffff,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"40To64/\"+c.description, func(t *testing.T) {\n\t\t\tconverted := utils.Uint40To64(c.u40)\n\n\t\t\tif diff := cmp.Diff(converted, c.u64); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"64To40/\"+c.description, func(t *testing.T) {\n\t\t\tconverted := utils.Uint64To40(c.u64)\n\n\t\t\tif diff := cmp.Diff(converted, c.u40); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestPLMN(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tmcc, mnc    string\n\t\tencoded     []byte\n\t}{\n\t\t{\n\t\t\t\"2-digit\",\n\t\t\t\"123\", \"45\",\n\t\t\t[]byte{0x21, 0xf3, 0x54},\n\t\t}, {\n\t\t\t\"3-digit\",\n\t\t\t\"123\", \"456\",\n\t\t\t[]byte{0x21, 0x63, 0x54},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"serialize/\"+c.description, func(t *testing.T) {\n\t\t\tencoded, err := utils.EncodePLMN(c.mcc, c.mnc)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(encoded, c.encoded); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\n\t\tt.Run(\"Decode/\"+c.description, func(t *testing.T) {\n\t\t\tmcc, mnc, err := utils.DecodePLMN(c.encoded)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif diff := cmp.Diff(mcc, c.mcc); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t\tif diff := cmp.Diff(mnc, c.mnc); diff != \"\" {\n\t\t\t\tt.Error(diff)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  }
]