mirror of
https://github.com/go-i2p/go-i2cp.git
synced 2025-06-07 01:01:09 -04:00
Finished sessions, only datagrams left
This commit is contained in:
30
client.go
30
client.go
@ -6,6 +6,7 @@ import (
|
||||
"compress/zlib"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@ -94,6 +95,8 @@ type Client struct {
|
||||
lookupRequestId uint32
|
||||
}
|
||||
|
||||
var defaultConfigFile = "/.i2cp.conf"
|
||||
|
||||
// NewClient creates a new i2p client with the specified callbacks
|
||||
func NewClient(callbacks ClientCallBacks) (c *Client) {
|
||||
c = new(Client)
|
||||
@ -112,10 +115,28 @@ func NewClient(callbacks ClientCallBacks) (c *Client) {
|
||||
func (c *Client) setDefaultProperties() {
|
||||
c.properties[CLIENT_PROP_ROUTER_ADDRESS] = "127.0.0.1"
|
||||
c.properties[CLIENT_PROP_ROUTER_PORT] = "7654"
|
||||
// TODO PARSE I2CP config file
|
||||
home := os.Getenv("HOME")
|
||||
if len(home) == 0 {
|
||||
return
|
||||
}
|
||||
config := home + defaultConfigFile
|
||||
Debug(CLIENT, "Loading config file %s", config)
|
||||
ParseConfig(config, func(name, value string) {
|
||||
if prop := c.propFromString(name); prop >= 0 {
|
||||
c.SetProperty(prop, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) propFromString(name string) ClientProperty {
|
||||
for i := 0; ClientProperty(i) < NR_OF_I2CP_CLIENT_PROPERTIES; i++ {
|
||||
if sessionOptions[i] == name {
|
||||
return ClientProperty(i)
|
||||
}
|
||||
}
|
||||
return ClientProperty(-1)
|
||||
}
|
||||
|
||||
// TODO Write messageGetDate
|
||||
func (c *Client) messageGetDate(queue bool) {
|
||||
Debug(PROTOCOL, "Sending GetDateMessage")
|
||||
c.messageStream.Reset()
|
||||
@ -576,12 +597,13 @@ func (c *Client) ProcessIO() error {
|
||||
}
|
||||
}
|
||||
c.lock.Unlock()
|
||||
var err error
|
||||
for c.tcp.CanRead() {
|
||||
if err := c.recvMessage(I2CP_MSG_ANY, c.messageStream, true); err != nil {
|
||||
if err = c.recvMessage(I2CP_MSG_ANY, c.messageStream, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) DestinationLookup(session *Session, address string) (requestId uint32) {
|
||||
|
@ -1,14 +1,12 @@
|
||||
package go_i2cp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
|
@ -1,9 +1,7 @@
|
||||
package go_i2cp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"errors"
|
||||
"github.com/cryptix/go/crypt"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
@ -86,7 +84,7 @@ func NewDestinationFromBase64(base64 string) (dest Destination, err error) {
|
||||
return NewDestinationFromMessage(&decoded)
|
||||
}
|
||||
|
||||
func NewDestinationFromFile(file os.File) (dest Destination, err error) {
|
||||
func NewDestinationFromFile(file *os.File) (dest Destination, err error) {
|
||||
var stream Stream
|
||||
stream.loadFile(file)
|
||||
return NewDestinationFromStream(&stream)
|
||||
|
12
i2pc.go
12
i2pc.go
@ -1,13 +1 @@
|
||||
package go_i2cp
|
||||
|
||||
func Init() {
|
||||
tcpInit()
|
||||
}
|
||||
|
||||
func Deinit() {
|
||||
tcpDeinit()
|
||||
}
|
||||
|
||||
const (
|
||||
CLIENT uint32 = (iota + 1) << 8
|
||||
)
|
||||
|
22
lease.go
Normal file
22
lease.go
Normal file
@ -0,0 +1,22 @@
|
||||
package go_i2cp
|
||||
|
||||
type Lease struct {
|
||||
tunnelGateway [32]byte // sha256 of the RouterIdentity of the tunnel gateway
|
||||
tunnelId uint32
|
||||
endDate uint64
|
||||
}
|
||||
|
||||
func NewLeaseFromStream(stream *Stream) (l *Lease, err error) {
|
||||
l = &Lease{}
|
||||
stream.Read(l.tunnelGateway[:])
|
||||
l.tunnelId, err = stream.ReadUint32()
|
||||
l.endDate, err = stream.ReadUint64()
|
||||
return
|
||||
}
|
||||
|
||||
func (l *Lease) WriteToMessage(stream *Stream) (err error) {
|
||||
_, err = stream.Write(l.tunnelGateway[:])
|
||||
err = stream.WriteUint32(l.tunnelId)
|
||||
err = stream.WriteUint64(l.endDate)
|
||||
return
|
||||
}
|
89
session.go
89
session.go
@ -1,10 +1,93 @@
|
||||
package go_i2cp
|
||||
|
||||
import "bytes"
|
||||
type SessionMessageStatus int
|
||||
|
||||
const (
|
||||
I2CP_MSG_STATUS_AVAILABLE SessionMessageStatus = iota
|
||||
I2CP_MSG_STATUS_ACCEPTED
|
||||
I2CP_MSG_STATUS_BEST_EFFORT_SUCCESS
|
||||
I2CP_MSG_STATUS_BEST_EFFORT_FAILURE
|
||||
I2CP_MSG_STATUS_GUARANTEED_SUCCESS
|
||||
I2CP_MSG_STATUS_GUARANTEED_FAILURE
|
||||
I2CP_MSG_STATUS_LOCAL_SUCCESS
|
||||
I2CP_MSG_STATUS_LOCAL_FAILURE
|
||||
I2CP_MSG_STATUS_ROUTER_FAILURE
|
||||
I2CP_MSG_STATUS_NETWORK_FAILURE
|
||||
I2CP_MSG_STATUS_BAD_SESSION
|
||||
I2CP_MSG_STATUS_BAD_MESSAGE
|
||||
I2CP_MSG_STATUS_OVERFLOW_FAILURE
|
||||
I2CP_MSG_STATUS_MESSAGE_EXPIRED
|
||||
I2CP_MSG_STATUS_MESSAGE_BAD_LOCAL_LEASESET
|
||||
I2CP_MSG_STATUS_MESSAGE_NO_LOCAL_TUNNELS
|
||||
I2CP_MSG_STATUS_MESSAGE_UNSUPPORTED_ENCRYPTION
|
||||
I2CP_MSG_STATUS_MESSAGE_BAD_DESTINATION
|
||||
I2CP_MSG_STATUS_MESSAGE_BAD_LEASESET
|
||||
I2CP_MSG_STATUS_MESSAGE_EXPIRED_LEASESET
|
||||
I2CP_MSG_STATUS_MESSAGE_NO_LEASESET
|
||||
)
|
||||
|
||||
type SessionStatus int
|
||||
|
||||
const (
|
||||
I2CP_SESSION_STATUS_DESTROYED SessionStatus = iota
|
||||
I2CP_SESSION_STATUS_CREATED
|
||||
I2CP_SESSION_STATUS_UPDATED
|
||||
I2CP_SESSION_STATUS_INVALID
|
||||
)
|
||||
|
||||
type SessionCallbacks struct {
|
||||
onMessage func(session *Session, protocol uint8, srcPort, destPort uint16, payload *Stream)
|
||||
onStatus func(session *Session, status SessionStatus)
|
||||
onDestination func(session *Session, requestId uint32, address string, dest *Destination)
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
id uint16
|
||||
config *SessionConfig
|
||||
client *Client
|
||||
callbacks *SessionCallbacks
|
||||
}
|
||||
|
||||
func (session Session) dispatchMessage(protocol uint8, srcPort, destPort uint16, payload *Stream) {
|
||||
|
||||
func NewSession(client *Client, callbacks SessionCallbacks, destFilename string) (sess *Session) {
|
||||
sess = &Session{}
|
||||
sess.client = client
|
||||
sess.config = &SessionConfig{}
|
||||
sess.callbacks = &callbacks
|
||||
return
|
||||
}
|
||||
func (session *Session) SendMessage(destination *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, nonce uint32) {
|
||||
session.client.msgSendMessage(session, destination, protocol, srcPort, destPort, payload, nonce, true)
|
||||
}
|
||||
func (session *Session) Destination() *Destination {
|
||||
return session.config.destination
|
||||
}
|
||||
func (session *Session) dispatchMessage(protocol uint8, srcPort, destPort uint16, payload *Stream) {
|
||||
if session.callbacks == nil || session.callbacks.onMessage == nil {
|
||||
return
|
||||
}
|
||||
session.callbacks.onMessage(session, protocol, srcPort, destPort, payload)
|
||||
}
|
||||
|
||||
func (session *Session) dispatchDestination(requestId uint32, address string, destination *Destination) {
|
||||
if session.callbacks == nil || session.callbacks.onDestination == nil {
|
||||
return
|
||||
}
|
||||
session.callbacks.onDestination(session, requestId, address, destination)
|
||||
}
|
||||
|
||||
func (session *Session) dispatchStatus(status SessionStatus) {
|
||||
switch status {
|
||||
case I2CP_SESSION_STATUS_CREATED:
|
||||
Debug(SESSION, "Session %p is created", session)
|
||||
case I2CP_SESSION_STATUS_DESTROYED:
|
||||
Debug(SESSION, "Session %p is destroyed", session)
|
||||
case I2CP_SESSION_STATUS_UPDATED:
|
||||
Debug(SESSION, "Session %p is updated", session)
|
||||
case I2CP_SESSION_STATUS_INVALID:
|
||||
Debug(SESSION, "Session %p is invalid", session)
|
||||
}
|
||||
if session.callbacks == nil || session.callbacks.onStatus == nil {
|
||||
return
|
||||
}
|
||||
session.callbacks.onStatus(session, status)
|
||||
}
|
||||
|
166
session_config.go
Normal file
166
session_config.go
Normal file
@ -0,0 +1,166 @@
|
||||
package go_i2cp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SessionConfigProperty int
|
||||
|
||||
const (
|
||||
SESSION_CONFIG_PROP_CRYPTO_LOW_TAG_THRESHOLD SessionConfigProperty = iota
|
||||
SESSION_CONFIG_PROP_CRYPTO_TAGS_TO_SEND
|
||||
|
||||
SESSION_CONFIG_PROP_I2CP_DONT_PUBLISH_LEASE_SET
|
||||
SESSION_CONFIG_PROP_I2CP_FAST_RECEIVE
|
||||
SESSION_CONFIG_PROP_I2CP_GZIP
|
||||
SESSION_CONFIG_PROP_I2CP_MESSAGE_RELIABILITY
|
||||
SESSION_CONFIG_PROP_I2CP_PASSWORD
|
||||
SESSION_CONFIG_PROP_I2CP_USERNAME
|
||||
|
||||
SESSION_CONFIG_PROP_INBOUND_ALLOW_ZERO_HOP
|
||||
SESSION_CONFIG_PROP_INBOUND_BACKUP_QUANTITY
|
||||
SESSION_CONFIG_PROP_INBOUND_IP_RESTRICTION
|
||||
SESSION_CONFIG_PROP_INBOUND_LENGTH
|
||||
SESSION_CONFIG_PROP_INBOUND_LENGTH_VARIANCE
|
||||
SESSION_CONFIG_PROP_INBOUND_NICKNAME
|
||||
SESSION_CONFIG_PROP_INBOUND_QUANTITY
|
||||
|
||||
SESSION_CONFIG_PROP_OUTBOUND_ALLOW_ZERO_HOP
|
||||
SESSION_CONFIG_PROP_OUTBOUND_BACKUP_QUANTITY
|
||||
SESSION_CONFIG_PROP_OUTBOUND_IP_RESTRICTION
|
||||
SESSION_CONFIG_PROP_OUTBOUND_LENGTH
|
||||
SESSION_CONFIG_PROP_OUTBOUND_LENGTH_VARIANCE
|
||||
SESSION_CONFIG_PROP_OUTBOUND_NICKNAME
|
||||
SESSION_CONFIG_PROP_OUTBOUND_PRIORITY
|
||||
SESSION_CONFIG_PROP_OUTBOUND_QUANTITY
|
||||
|
||||
NR_OF_SESSION_CONFIG_PROPERTIES
|
||||
)
|
||||
|
||||
var sessionOptions = [NR_OF_SESSION_CONFIG_PROPERTIES]string{
|
||||
"crypto.lowTagThreshold",
|
||||
"crypto.tagsToSend",
|
||||
"i2cp.dontPublishLeaseSet",
|
||||
"i2cp.fastReceive",
|
||||
"i2cp.gzip",
|
||||
"i2cp.messageReliability",
|
||||
"i2cp.password",
|
||||
"i2cp.username",
|
||||
|
||||
"inbound.allowZeroHop",
|
||||
"inbound.backupQuantity",
|
||||
"inbound.IPRestriction",
|
||||
"inbound.length",
|
||||
"inbound.lengthVariance",
|
||||
"inbound.nickname",
|
||||
"inbound.quantity",
|
||||
|
||||
"outbound.allowZeroHop",
|
||||
"outbound.backupQuantity",
|
||||
"outbound.IPRestriction",
|
||||
"outbound.length",
|
||||
"outbound.lengthVariance",
|
||||
"outbound.nickname",
|
||||
"outbound.priority",
|
||||
"outbound.quantity",
|
||||
}
|
||||
var configRegex = regexp.MustCompile("\\s*([\\w.]+)=\\s*(.+)\\s*;\\s*")
|
||||
|
||||
type SessionConfig struct {
|
||||
properties [NR_OF_SESSION_CONFIG_PROPERTIES]string
|
||||
date uint64
|
||||
destination *Destination
|
||||
}
|
||||
|
||||
func NewSessionConfigFromDestinationFile(filename string) (config SessionConfig) {
|
||||
var home string
|
||||
if file, err := os.Open(filename); err == nil {
|
||||
dest, err := NewDestinationFromFile(file)
|
||||
config.destination = &dest
|
||||
if err != nil {
|
||||
Warning(SESSION_CONFIG, "Failed to load destination from file '%s', a new destination will be generated.", filename)
|
||||
}
|
||||
}
|
||||
if config.destination == nil {
|
||||
dest, err := NewDestination()
|
||||
config.destination = &dest
|
||||
}
|
||||
if len(filename) > 0 {
|
||||
config.destination.WriteToFile(filename)
|
||||
}
|
||||
home = os.Getenv("HOME")
|
||||
if len(home) > 0 {
|
||||
configFile := home + "/.i2cp.conf"
|
||||
ParseConfig(configFile, func(name, value string) {
|
||||
if prop := config.propFromString(name); prop >= 0 {
|
||||
config.SetProperty(prop, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
return config
|
||||
}
|
||||
func (config *SessionConfig) writeToMessage(stream *Stream) {
|
||||
config.destination.WriteToMessage(stream)
|
||||
config.writeMappingToMessage(stream)
|
||||
stream.WriteUint64(uint64(time.Now().Unix()))
|
||||
GetCryptoInstance().WriteSignatureToStream(&config.destination.sgk, stream)
|
||||
}
|
||||
func (config *SessionConfig) writeMappingToMessage(stream *Stream) (err error) {
|
||||
is := NewStream(make([]byte, 0xffff))
|
||||
count := 0
|
||||
for i := 0; i < int(NR_OF_SESSION_CONFIG_PROPERTIES); i++ {
|
||||
var option string
|
||||
if sc.properties[i] == "" {
|
||||
continue
|
||||
}
|
||||
option = sc.configOptLookup(SessionConfigProperty(i))
|
||||
if option == "" {
|
||||
continue
|
||||
}
|
||||
is.Write([]byte(option + "=" + sc.properties[i] + ";"))
|
||||
count++
|
||||
}
|
||||
Debug(SESSION_CONFIG, "Writing %d options to mapping table", count)
|
||||
err = stream.WriteUint16(uint16(is.Len()))
|
||||
if is.Len() > 0 {
|
||||
_, err = stream.Write(is.Bytes())
|
||||
}
|
||||
return
|
||||
}
|
||||
func (config *SessionConfig) configOptLookup(property SessionConfigProperty) string {
|
||||
return sessionOptions[property]
|
||||
}
|
||||
func (config *SessionConfig) propFromString(name string) SessionConfigProperty {
|
||||
for i := 0; SessionConfigProperty(i) < NR_OF_SESSION_CONFIG_PROPERTIES; i++ {
|
||||
if sessionOptions[i] == name {
|
||||
return SessionConfigProperty(i)
|
||||
}
|
||||
}
|
||||
return SessionConfigProperty(-1)
|
||||
}
|
||||
func (config *SessionConfig) SetProperty(prop SessionConfigProperty, value string) {
|
||||
config.properties[prop] = value
|
||||
}
|
||||
func ParseConfig(s string, cb func(string, string)) {
|
||||
file, err := os.Open(s)
|
||||
if err != nil {
|
||||
Error(SESSION_CONFIG, err.Error())
|
||||
return
|
||||
}
|
||||
Debug(SESSION_CONFIG, "Parsing config file '%s'", s)
|
||||
scan := bufio.NewScanner(file)
|
||||
for scan.Scan() {
|
||||
line := scan.Text()
|
||||
groups := configRegex.FindStringSubmatch(line)
|
||||
if len(groups) != 3 {
|
||||
continue
|
||||
}
|
||||
cb(groups[1], groups[2])
|
||||
}
|
||||
if err := scan.Err(); err != nil {
|
||||
Error(SESSION_CONFIG, "reading input from %s config %s", s, err.Error())
|
||||
}
|
||||
}
|
17
stream.go
17
stream.go
@ -1,32 +1,31 @@
|
||||
package go_i2cp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"encoding/binary"
|
||||
"bytes"
|
||||
"io"
|
||||
"encoding/binary"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Stream = bytes.Buffer
|
||||
|
||||
func NewStream(buf []byte) *Stream {
|
||||
return bytes.NewBuffer(buf)
|
||||
}
|
||||
func (s *Stream) ReadUint16() (r uint16, err error) {
|
||||
bts := make([]byte, 2)
|
||||
_, err = s.Read(bts)
|
||||
_, err = s.Read(bts)
|
||||
r = binary.LittleEndian.Uint16(bts)
|
||||
return
|
||||
}
|
||||
func (s *Stream) ReadUint32() (r uint32, err error) {
|
||||
bts := make([]byte, 4)
|
||||
_, err = s.Read(bts)
|
||||
_, err = s.Read(bts)
|
||||
r = binary.LittleEndian.Uint32(bts)
|
||||
return
|
||||
}
|
||||
func (s *Stream) ReadUint64() (r uint64, err error) {
|
||||
bts := make([]byte, 8)
|
||||
_, err = s.Read(bts)
|
||||
_, err = s.Read(bts)
|
||||
r = binary.LittleEndian.Uint64(bts)
|
||||
return
|
||||
}
|
||||
@ -49,7 +48,7 @@ func (s *Stream) WriteUint64(i uint64) (err error) {
|
||||
_, err = s.Write(bts)
|
||||
return
|
||||
}
|
||||
func (s *Stream) loadFile(f os.File) (err error) {
|
||||
func (s *Stream) loadFile(f *os.File) (err error) {
|
||||
_, err = f.Read(s.Bytes())
|
||||
return
|
||||
}
|
||||
@ -113,4 +112,4 @@ func (s *Stream) ReadUint8p(len uint32) []uint8 {
|
||||
defer s.Skip(len)
|
||||
return s.data[s.p:len]
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
115
tcp.go
115
tcp.go
@ -1,35 +1,114 @@
|
||||
package go_i2cp
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
func tcpInit() {
|
||||
address = net.TCPAddr{
|
||||
IP: net.ParseIP("127.0.0.1"),
|
||||
Port: 7654,
|
||||
}
|
||||
type TcpProperty int
|
||||
|
||||
const (
|
||||
TCP_PROP_ADDRESS TcpProperty = iota
|
||||
TCP_PROP_PORT
|
||||
TCP_PROP_USE_TLS
|
||||
TCP_PROP_TLS_CLIENT_CERTIFICATE
|
||||
NR_OF_TCP_PROPERTIES
|
||||
)
|
||||
|
||||
var CAFile = "/etc/ssl/certs/ca-certificates.crt"
|
||||
var defaultRouterAddress = "127.0.0.1:7654"
|
||||
|
||||
const USE_TLS = true
|
||||
|
||||
func (tcp *Tcp) Init() (err error) {
|
||||
tcp.address, err = net.ResolveTCPAddr("tcp", defaultRouterAddress)
|
||||
return
|
||||
}
|
||||
|
||||
func tcpDeinit() {
|
||||
|
||||
}
|
||||
|
||||
var address net.TCPAddr
|
||||
var conn *net.TCPConn
|
||||
|
||||
func (tcp *Tcp) Connect() (err error) {
|
||||
conn, err = net.DialTCP("tcp", nil, &address )
|
||||
if USE_TLS {
|
||||
roots, err := x509.SystemCertPool()
|
||||
tcp.tlsConn, err = tls.Dial("tcp", tcp.address.String(), &tls.Config{RootCAs: roots})
|
||||
err = tcp.tlsConn.Handshake()
|
||||
} else {
|
||||
tcp.conn, err = net.DialTCP("tcp", nil, tcp.address)
|
||||
if err == nil {
|
||||
err = tcp.conn.SetKeepAlive(true)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (tcp *Tcp) Send(buf *Stream) (i int, err error) {
|
||||
i, err = conn.Write(buf.Bytes())
|
||||
if USE_TLS {
|
||||
i, err = tcp.tlsConn.Write(buf.Bytes())
|
||||
} else {
|
||||
i, err = tcp.conn.Write(buf.Bytes())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (tcp *Tcp) Receive(buf *Stream) (i int, err error) {
|
||||
i, err = conn.Read(buf.Bytes())
|
||||
if USE_TLS {
|
||||
i, err = tcp.tlsConn.Read(buf.Bytes())
|
||||
} else {
|
||||
i, err = tcp.conn.Read(buf.Bytes())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (tcp *Tcp) CanRead() bool {
|
||||
var one []byte
|
||||
if USE_TLS {
|
||||
tcp.tlsConn.SetReadDeadline(time.Now())
|
||||
if _, err := tcp.tlsConn.Read(one); err == io.EOF {
|
||||
Debug(TCP, "%s detected closed LAN connection", tcp.address.String())
|
||||
defer tcp.Disconnect()
|
||||
return false
|
||||
} else {
|
||||
var zero time.Time
|
||||
tcp.tlsConn.SetReadDeadline(zero)
|
||||
return tcp.tlsConn.ConnectionState().HandshakeComplete
|
||||
}
|
||||
} else {
|
||||
tcp.conn.SetReadDeadline(time.Now())
|
||||
if _, err := tcp.conn.Read(one); err == io.EOF {
|
||||
Debug(TCP, "%s detected closed LAN connection", tcp.address.String())
|
||||
defer tcp.Disconnect()
|
||||
return false
|
||||
} else {
|
||||
var zero time.Time
|
||||
tcp.conn.SetReadDeadline(zero)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tcp *Tcp) Disconnect() {
|
||||
if USE_TLS {
|
||||
tcp.tlsConn.Close()
|
||||
} else {
|
||||
tcp.conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (tcp *Tcp) IsConnected() bool {
|
||||
return tcp.CanRead()
|
||||
}
|
||||
|
||||
func (tcp *Tcp) SetProperty(property TcpProperty, value string) {
|
||||
tcp.properties[property] = value
|
||||
}
|
||||
func (tcp *Tcp) GetProperty(property TcpProperty) string {
|
||||
return tcp.properties[property]
|
||||
}
|
||||
|
||||
type Tcp struct {
|
||||
|
||||
}
|
||||
address *net.TCPAddr
|
||||
conn *net.TCPConn
|
||||
tlsConn *tls.Conn
|
||||
properties [NR_OF_TCP_PROPERTIES]string
|
||||
}
|
||||
|
Reference in New Issue
Block a user